Kampagne oder Story? Wo aSPARK die Grenze zieht
Seit v0.13.0 kennt aSPARK zwei Arbeitsweisen: den Feature-Loop für Stories und Kampagnen für Arbeit, deren Ende ein Befehl feststellen kann. Wann welche passt, was keine Kampagne ist und woran der Agent das selbst prüft.
Seit v0.13.0 gibt es in aSPARK zwei Arbeitsweisen. Der Feature-Loop trägt eine User Story von der Spec bis zum Release. Eine Kampagne arbeitet in Iterationen auf ein Ziel hin, bis es erreicht ist oder eine Stopp-Regel greift. Beide haben Gates, beide lassen dich entscheiden. Sie lösen aber verschiedene Probleme, und wer sie verwechselt, bekommt entweder eine Fake-Story oder ein Epic durch die Hintertür.
Die Grenze passt in einen Satz:
Muss ein Mensch beurteilen, ob das Ergebnis gut ist, ist es eine Story. Kann ein Befehl feststellen, ob die Arbeit fertig ist, kann es eine Kampagne sein.
Die Story: neues Verhalten, das jemand beurteilt
Eine Story beschreibt etwas, das es danach gibt und vorher nicht: einen Filter, eine Seite, einen Export. Die Akzeptanzkriterien sind testbar, aber ob das Ganze stimmt, entscheidest du an Gates. Der Product Owner hinterfragt die Idee, bei UI-Features prüft der Designer die Spec, die QA klickt die App im Browser durch. Das ist Urteilsarbeit, und genau dafür ist der Loop gebaut.
Die Kampagne: ein prüfbarer Endzustand und viel Wiederholung
Eine Kampagne hat kein neues Verhalten als Ziel, sondern einen Zustand. „Jede Scheibe der Migration ist parity-green.“ Dazu gehören laut Vorlage (templates/campaign.md) eine Bedingung, eine Beobachtung, die sie bestätigt (ein Befehl mit Ausgabe oder ein Dateizustand), wer prüft, und Schwellen, die fertig von nicht fertig trennen.
Bevor eine Kampagne startet, wird ein Veto-Protokoll ausgefüllt:
| Bedingung | Art |
|---|---|
| Die Prüfung ist automatisch ausführbar: der Agent kann sie laufen lassen und das Ergebnis sehen | Pflicht. Fehlt sie, ist das ein Stopp, außer du trägst selbst eine begründete Ausnahme ein |
| Die Arbeit wiederholt sich | Hinweis, wird nur vermerkt |
| Das Budget ist bezahlbar | Hinweis |
| Der Agent hat Werkzeuge, die die Prüfung ausführen | Hinweis |
Dazu kommen ein Budget aus Iterationen und Tokens und Stopp-Regeln, die anhalten und dich fragen: zweimal kein Fortschritt, zweimal derselbe Fehler, Budget überschritten, Merge-Konflikt. Die Migrations-Art ergänzt eigene, etwa SR-5: Eine schon grüne Scheibe wird rot.
Beispiele
| Vorhaben | Arbeitsweise | Warum |
|---|---|---|
| „Ein Dashboard mit Wochenstatistik“ | Story | Neues Verhalten, gut oder nicht gut entscheidet ein Mensch |
„Alle Module von old/ nach new/, Parity-Check grün“ |
Kampagne (migration-campaign) |
Ein Befehl sagt, ob es fertig ist; derselbe Schritt pro Scheibe |
| „Der Code soll sauberer werden“ | weder noch, so formuliert | Nicht entscheidbar. Entweder ein messbares Ziel daraus machen oder als Feature planen |
| „Neue Doku-Seite und ein Export-Feature mit drei Stories“ | Feature-Loop | Mehrere unabhängige Ziele, also mehrere Stories |
| „Alle offenen Major-Findings schließen“ | Form einer Kampagne | Prüfbar und wiederholt. Heute gibt es aber nur die Migrations-Art, eine passende Art fehlt noch |
Was keine Kampagne ist, prüft der Agent selbst
Die Grenze steht nicht nur in der Doku. Sie steht in der Kampagnen-Datei, und der Agent muss sie vor der ersten Iteration prüfen. Zwei echte Antworten aus der QA von campaign-core, beide auf einem Test-Repo:
Ein Ziel „der Code sieht sauber aus“:
I didn't start the campaign. The goal fails the campaign's own rules, so I'm not going to iterate on it. [...] §1 also says "It looks good is not decidable and is rejected", and this goal is that same statement reworded.
Eine Kampagne, in deren Datei ein zweites Ziel steht, eine neue Doku-Seite und ein Export-Feature mit drei Stories:
That goal is a set of user stories, which the file says belongs in the feature loop.
In beiden Fällen blieb die Datei unverändert, es lief keine Iteration. Die Regel dahinter heißt in der Vorlage „eine Unternehmung, ein Ziel, ein Budget“. Mehrere Ziele oder ein Bündel Stories gehören in den Feature-Loop, sonst wäre die Kampagne ein Epic durch die Hintertür.
Wo sich beide berühren
Eine Kampagne löscht nichts auf eigene Faust. Bei der Migration ist das Entfernen des alten Codes ein eigener Schritt pro Scheibe, erst nach Grün und erst auf dein ausdrückliches Go. Auch wenn du die Kampagne als complete markierst, ist das keine Erlaubnis dafür.
Und Features laufen parallel weiter. Für diesen Fall ist eine Regel festgelegt: Ein Feature, das eine Scheibe einer laufenden Migration berührt, nennt die Kampagne in seiner Spec und lässt den Parity-Check dieser Scheibe vor dem Merge grün laufen. Features, die nichts damit zu tun haben, merken nichts. Diese Regel ist geschrieben, greift aber erst, wenn das Routing kommt.
Was noch fehlt
Heute entscheidest du selbst, welche Arbeitsweise passt, und startest eine Kampagne von Hand. Geplant ist, dass /spark und /story-time einen prüfbaren Endzustand erkennen, die Kampagne vorschlagen und eine als Kampagne getarnte Story zurück in den Feature-Loop schicken. Als Nächstes in Arbeit ist ein Befehl /campaign, der aus deinem Ziel einen Entwurf schreibt und Story-förmige Anfragen gleich abweist.
Warum ich Kampagnen überhaupt gebaut habe, steht auf meinem Blog: Meinem Agenten fehlte ein Abbruchkriterium.
Kampagnen sind experimentell. Die Stopp-Regeln befolgt der Agent, erzwungen werden sie nicht, und gelaufen sind sie bisher auf Test-Repos. Die Formate und Regeln stehen in campaigns/README.md und templates/campaign.md.