Zum Inhalt springen
Farbschema wählenSprache wählen

Ein spec-getriebenes Projekt betreiben

Diese Anleitung richtet ein Projekt für spec-getriebene Lieferung ein: Specs und Work-Item-Verträge in deinem Repository, die Gates, die jede Änderung daran festhalten, die Bereitschaft in deinem Tracker und ein SupaCloud-Projekt, das am Ergebnis arbeitet. Die Idee dahinter erklärt zuerst Spec-getriebene Lieferung.

  1. Lege specs/ an, mit den Schemas in specs/_schema/ und der Template-Domäne in specs/_template/. Hat deine Kopie der Schemas noch keinen Versions-Lock, schreibe den ersten mit uv run python tools/specs/validate.py --init-lock; danach aktualisiert --write-lock ihn, und ein fehlender Lock lässt die Validierung fehlschlagen.

  2. Schreibe specs/project.yaml, das Projektprofil, vor allem anderen. Es ist das, was das Format zu deinem Projekt passend macht: wo dein Anforderungskatalog liegt, welche seiner Listen Anforderungen, Abnahmekriterien und Entscheidungsakten enthalten, ein Muster mit Beispiel je Anforderungs-ID-Form, die du verwendest, und jede Einheit deiner Parameter mit ihrer Bedeutung. Es gibt keinen Standard — ohne diese Datei schlagen Validator, Spec-Gate und die Work-Item-Prüfungen fehl und nennen das fehlende Feld. Die Felder stehen im Delivery-Spec-Format.

  3. Kopiere das Template in deine erste Domäne, zum Beispiel specs/billing/, und ersetze den Domänencode TPL in jeder Datei und jeder ID (TPL-R-001 wird BILL-R-001).

  4. Schreibe zuerst die Klauseln in spec.yaml — je eine testbare Aussage in EARS-Form, mit den Anforderungen, die sie erfüllt. Jede Zahl gehört mit einem freigegebenen Bereich in parameters.yaml, nicht in den Klauseltext.

  5. Schreibe ein Szenario pro Verhalten in scenarios/, mit konkreten Werten. Die Szenarien sind das Test-Orakel, schreibe die erwarteten Werte also selbst, statt sie dem Agenten zu überlassen, der die Klausel umsetzen wird.

  6. Trage jede offene Designfrage mit ihren Optionen, einer empfohlenen Option und der Begründung in decisions.yaml ein und jede Lücke in questions.yaml. Lass den Status auf draft.

  7. Richte scope.paths auf den Code, der die Domäne umsetzt, und validiere dann:

    Terminal-Fenster
    uv run python tools/specs/validate.py specs/billing
    uv run python tools/qa/check_specs.py

    Beide müssen null Befunde melden. Übernimmt eine Domäne Katalog-IDs, muss die Abdeckungs-Baseline des Spec-Gates in derselben Änderung neu geschrieben werden (--write-baseline): Diese Baseline muss der Anzahl der Katalog-IDs, die keine Domäne besitzt, gleichen, damit Spielraum darin den nächsten Rückschritt nicht verdecken kann. Das Format, Feld für Feld, steht im Delivery-Spec-Format.

  1. Beantworte jede Entscheidung in decisions.yaml. Heute tust du das außerhalb von SupaCloud — in einem Fragebogen, im Review des Spec-Pull-Requests oder von Hand — und hältst jede Antwort im answer-Block der Entscheidung mit choice, answered_by, answered_at und source fest; dann setzt du ihren Status auf approved. Decision Briefs in SupaCloud sind geplant (SC-29).

  2. Bestätige jede Empfehlung, die du übernimmst. Eine vorausgewählte Empfehlung, die niemand bestätigt hat, ist keine Antwort: Lass eine solche Entscheidung proposed, bis du sie wirklich getroffen hast.

  3. Beantworte oder ziehe jede offene Rückfrage zurück und setze dann im selben Pull Request den Status der Spec auf design-approved. Das Spec-Gate verweigert den Status, solange eine Entscheidung noch proposed oder eine Rückfrage noch open ist.

3. Work Items schreiben, die sich an Klauseln binden

Abschnitt betitelt „3. Work Items schreiben, die sich an Klauseln binden“
  1. Schreibe für jeden Ausschnitt einen Work-Item-Vertrag mit spec_refs (die Klauseln, die er umsetzt), decision_refs (die Entscheidungen, von denen er abhängt) und Abnahmeeinträgen, deren verifies die Klauseln nennt, die jeder Eintrag nachweist.

  2. Halte jedes Item bei höchstens sechs Klauseln und acht Abnahmeeinträgen; teile alles, was größer ist.

  3. Gib jedem Item eine Komplexitätsklasse (T0 bis T3). Sie legt fest, wie viele unabhängige Reviews die Änderung vor dem Merge braucht.

  4. Lass die Work-Item-Gates laufen, bis sie grün sind. Der vollständige Regelsatz steht im Spec-Bereitschaftsvertrag.

  1. Lass das Spec-Gate und die Work-Item-Gates in deiner CI bei jedem Pull Request laufen.

  2. Verlange diese Checks auf deinem Haupt-Branch über den Branch-Schutz.

  3. Füge einen Pflicht-Status für die Gate-Klassen hinzu, den nur der Freigebende der Klasse grün macht, und verlange ihn ebenfalls: dich für G1 bis G5 und für die Gate-Karte selbst; für die Security-Review-Klassen (S1 neue Abhängigkeiten, S2 CI-Workflows, S3 Security-Werkzeuge und Gate-Konfiguration) den automatisierten Security-Reviewer, sobald es ihn gibt (geplant), und bis dahin dich. Die Version dieses Status in der Referenzimplementierung heißt gate-class und ist auf deren Haupt-Branch neben ihren drei CI-Kontexten erforderlich — übernimm diese Form:

    • Der Basis-Branch urteilt. Der Job holt Klassenkarte und Prüfer aus dem Basis-Branch und liest den Pull-Request-Head nur als Daten, ein Pull Request kann die Regeln, nach denen er beurteilt wird, also nicht lockern. Lege Karte, Prüfer und Workflow selbst in eine Owner-Klasse.
    • Lass ihn bei jedem Ereignis laufen, das das Urteil ändern kann: ein neuer oder umgehängter Head, ein abgegebenes oder bearbeitetes Review und ein erstellter, bearbeiteter oder gelöschter Freigabe-Kommentar.
    • Binde die Freigabe an den Head-Commit, damit ein neuer Push eine neue Freigabe braucht und ein verworfenes oder veraltetes Review nicht zählt.
    • Lehnt deine Forge Selbstfreigaben ab, wie Forgejo es tut, akzeptiere einen Kommentar, der den Commit nennt (/approve-gates <sha>), als deine Freigabe eines Pull Requests, den du geschrieben hast — aber zähle niemals einen bearbeiteten Kommentar, denn jeder mit Schreibrecht kann jeden Kommentar bearbeiten.
    • Ein Änderungswunsch des Reviewers eskaliert die Security-Review-Klassen an dich.
    • Er braucht kein Secret und keinen Bot-Account: Das eigene CI-Job-Token der Forge liest den Pull Request, seine Reviews und seine Kommentare und setzt den Status.
    • Kenne die Grenzen: Ein Instanz-Admin kann am Branch-Schutz vorbei force-mergen, und jeder Schreiber kann einen Status mit beliebigem Kontext setzen. Das Gate hält den autonomen Merge-Weg zuverlässig auf; es ist keine Verteidigung gegen eine absichtliche Fälschung.

    Solange du keinen solchen Status hast, halte Änderungen dieser Klassen hinter einem Merge, den du selbst machst.

  4. Erlaube Merge-Commits auf dem Haupt-Branch, oder rechne damit, dass die Merges von SupaCloud abgelehnt werden: SupaCloud mergt heute mit einem Merge-Commit, ein Repository, das nur Squash erlaubt, lehnt also jeden Merge ab, den es versucht. Merge-Stile pro Projekt sind geplant (SC-24).

Ein Work Item ist bereit, wenn seine Abhängigkeiten geschlossen, seine Entscheidungen freigegeben und seine Spec design-approved oder weiter ist; ein bereites Item mit spec_refs ist spec-ready.

  1. Starte heute die Referenz-Synchronisation aus deiner eigenen Sitzung mit deinem eigenen Forge-Token. Sieh dir zuerst die geplanten Schreibvorgänge an, wende sie dann an und prüfe danach:

    Terminal-Fenster
    export FORGEJO_TOKEN=# dein Token; nie committen und nie als CI-Secret ablegen
    uv run python tools/fmctl.py workitems sync -- --dry-run
    uv run python tools/fmctl.py workitems sync
    uv run python tools/fmctl.py workitems sync -- --check

    Die Prüfung darf keine Fehler melden. Starte die Synchronisation erneut, wann immer eine Entscheidung beantwortet wird, eine Spec ihren Status ändert oder ein Issue geschlossen wird.

  2. Lege dafür keinen CI-Job, keinen Bot-Account und kein Repository-Secret an. Wenn SupaCloud die Bereitschaft selbst berechnet (geplant, SC-2 mit SC-20), wird es über die Forge-Verbindung, die dein Projekt schon hat, der einzige Schreiber dieser Labels, und du startest die Synchronisation nicht mehr.

  1. Starte spec-ready-Issues vorerst selbst. Der Backlog von SupaCloud liest noch keine Labels: Im Modus Backlog würde sein Klassifikator auch offene Issues dispatchen, die blocked sind oder die Entscheidungen statt Arbeit sind. Im Web-Terminal listet issues <project> sie auf, und run <project> <agent> --issue <n> startet eines — siehe Einen Task aus einem Issue starten. Genau die spec-ready-Issues zu dispatchen, ist geplant (SC-2).

  2. Wenn du den Backlog doch laufen lässt, setze seine Merge-Richtlinie ausdrücklich. Wähle Nur PR (manueller Merge), solange du selbst mergst, oder Auto-Merge bei grün mit dem Branch-Schutz aus Schritt 4 als Rückhalt. Wähle für ein spec-getriebenes Projekt nie Voll autonom: Es hat keinen Rückfall für sensible Änderungen. Der Autonomieregler senkt die Merge-Richtlinie, die du setzt, immer nur ab, ein ausdrückliches Auto-Merge bei grün bleibt also auch auf der höchsten Autonomiestufe in Kraft — siehe Die Autonomiestufe festlegen.

  3. Lass Agenten fragen statt raten. Ein Agent, der auf eine Lücke stößt, stellt mit question.ask eine Rückfrage; du beantwortest sie im Eingang oder auf der Chat-Karte — siehe Einen Agenten nachfragen lassen. Halte die Antwort heute selbst per Pull Request in der Spec fest (als Entscheidung oder als answer der Rückfrage); sie automatisch zurückzuschreiben, ist geplant (SC-10).

  • uv run python tools/qa/check_specs.py und die Work-Item-Gates melden auf main null Befunde.
  • uv run python tools/fmctl.py workitems sync -- --check meldet keine Fehler, und jedes offene Work Item trägt genau eines von ready oder blocked.
  • Ein Pull Request, der Code unter den scope.paths einer Domäne ändert, ohne eine ihrer Klauseln in einer Commit-Nachricht zu nennen, färbt das Spec-Gate rot.
  • specs/project.yaml zu löschen färbt Validator, Spec-Gate und die Work-Item-Prüfungen rot und nennt die Datei — nichts fällt auf fremde ID-Formen zurück.
  • Ein Pull Request mit einem fehlschlagenden Pflicht-Check kann nicht gemergt werden — weder von dir noch von SupaCloud.
  • Ein Pull Request, der eine Entscheidung beantwortet oder den freigegebenen Bereich eines Parameters verschiebt, zeigt den Gate-Status als wartend, bis du genau diesen Commit freigibst, und ein neuer Push setzt ihn wieder auf wartend.