Zum Inhalt springen
Farbschema wählenSprache wählen

Wie SupaCloud sich in ein spec-getriebenes Projekt einfügt

Ein spec-getriebenes Projekt hält sein Verhalten in versionierten Specs und seine Arbeit in kleinen Verträgen, die sich an Spec-Klauseln binden. Menschen entscheiden vor der Arbeit, Gates entscheiden danach, und ein Orchestrator treibt die Schleife dazwischen. SupaCloud soll dieser Orchestrator sein. Diese Seite erklärt, wo es andockt, was jeder Integrationspunkt im Code auf main heute tut und was noch zu bauen ist. Die Entscheidung dahinter ist ADR 0075; die Dateien stehen im Delivery-Spec-Format, die Work-Item-Seite und die Labels im Spec-Bereitschaftsvertrag.

Anforderungskatalog was das Produkt bieten muss
│ eine Klausel zitiert, was sie erfüllt
Domänen-Spec (specs/<dom>/) wie es sich verhält: Klauseln, Parameter, Szenarien, Entscheidungen
│ G1-Entscheidungen beantwortet ──► Status design-approved
Work Items (WI-*.yaml) welcher Ausschnitt als Nächstes kommt: spec_refs, decision_refs, verifies
│ Bereitschaft ──► Tracker-Labels ready / blocked / spec-ready [1 Aufnahme]
Agentenlauf nach Tier geroutet, auf einem freigegebenen Ausschnitt [2 Dispatch]
│ eine Lücke ──► Rückfrage ──► Antwort ──► Entscheidung ──► Spec-Patch [3 Rückfrage, 4 Briefs]
Pull Request + Evidence CI, Spec-Gate, Audit, unabhängiges Review
│ jeder Pflicht-Check grün auf demselben Head-SHA ──► Merge [5 Merge]
Spec-Vertrag validiert, nachverfolgt, angezeigt [6 Vertrag]

Eine untere Ebene ändert nie still eine obere. Eine Lücke, die bei der Umsetzung auffällt, wird eine Rückfrage in der Spec, keine Annahme im Code, und die Antwort kommt als Entscheidung zurück, die wie jede andere Änderung gemergt wird.

Was die Schleife braucht. Bereitschaft ist eine Tatsache, die aus dem Repository berechnet wird: Abhängigkeiten geschlossen, referenzierte Entscheidungen freigegeben, referenzierte Specs design-approved oder weiter. SupaCloud berechnet sie, schreibt als einziger Tracker-Schreiber des Projekts die Labels ready, blocked, spec-ready und human-gate und dispatcht genau die spec-ready-Items.

Heute. SupaCloud liest und schreibt keine Issue-Labels.

  • Das Forgejo-Issue, das es deserialisiert, trägt id, number, title, state, body, html_url und created_at — keine Labels, keinen Meilenstein (server/crates/sc-forge/src/git/forgejo.rs:77-85); sc-forge hat überhaupt keinen Aufruf, der Labels liest oder schreibt.
  • Die Aufnahme ist ein Poll alle 300 Sekunden (server/crates/sc-svc-orchestration/src/backlog/mod.rs:27) über höchstens 100 offene Issues (server/crates/sc-forge/src/git/forgejo_issues.rs:30,56).
  • Die Bereitschaft kommt vom Klassifikator: ready wird queued, needs_info wird needs_info (server/crates/sc-svc-orchestration/src/backlog/classify.rs:5-6), mit dem LLM-Klassifikator als Standard.
  • Die Backlog-Lane wertet keinen Gate-Filter aus (server/crates/sc-svc-orchestration/src/auto_developer_lane_filters.rs:102-112).

Geplant (SC-2, mit SC-20). Labels, Meilenstein, Zuständige und Zustand bei jedem Scan und bei Issue-Webhooks lesen; zum Dispatch-Zeitpunkt einen Label-Regelsatz auswerten (require_all, forbid_any, …); ein Item zurückhalten, dessen Labels nicht passen, und es abbrechen, wenn sein Issue geschlossen wird; ein Label das Profil und das Tier wählen lassen. Darüber hinaus macht die Owner-Entscheidung vom 22.09.2026 SupaCloud zum einzigen Schreiber: Es leitet die Bereitschaft selbst aus den Work-Item-Verträgen und Specs ab — die Referenzimplementierung ist bw-fm27 tools/workitems/sync.py (compute_ready, compute_spec_ready, load_spec_state) — und pflegt die Labels über die bestehende Forge-Verbindung des Projekts (resolve_forge_for_project, server/crates/sc-svc-projects/src/projects/credentials.rs:307, ist der Credential-Pfad, den der Merge schon nutzt). Kein Bot-Account, kein CI-Secret.

Was die Schleife braucht. Work Items und Routing nennen eine Fähigkeitsstufe (Tier), nie ein Modell. Der Kalibrator entscheidet anhand gemessener Belege, welches Modell hinter jedem Tier steht.

Heute. Die Tiers gibt es — flagship, balanced, fast, independent_review (server/crates/sc-kernel/src/model_tier.rs:27-34), die Schreibweise independent-review wird akzeptiert —, und der Kalibrator schreibt geordnete Tier-Ketten und wendet sie automatisch an (ADR 0068; server/crates/sc-svc-orchestration/src/calibration/auto_apply.rs). Aber kein Arbeitsstart kann „nimm Tier X” sagen: Die Modell-Policy eines Agent-Profils ist manual, fixed oder auto (server/crates/sc-persistence/src/models/agent_profile.rs:28-32), und das Tier eines Tasks wird aus seinem festgelegten Modell abgeleitet.

Geplant (SC-3). model_policy = tier für Profile und ein tier pro Pipeline-Stufe, beim Start auf den ersten erreichbaren Eintrag der kalibrierten Kette aufgelöst; ein per Label geroutetes Item trägt sein Tier; ein unerreichbares Tier stellt das Item zurück, statt still den Runner-Standard zu nehmen. Das unabhängige zweite Review eines anderen Anbieters (SC-4) baut auf dem Tier independent_review auf; heute hat die Pipeline genau einen Review-Slot (server/crates/sc-svc-orchestration/src/auto_developer_pipeline.rs:100-110). Der Owner hat am 22.09.2026 entschieden, zusätzlich einen automatisierten Security-Reviewer einzuführen: eine Kalibrator-Lane security_review mit eigenen Belegen und eigener Akzeptanz-Telemetrie und einen Security-Slot in SC-4, der bei Security-Review-Gate-Klassen greift (neue Abhängigkeitsnamen, CI-Workflows, Security-Werkzeuge, Secrets, Auth- und Vertrauensgrenzen-Code). Seine Freigabe gibt diese Klassen frei; eine Änderungsanforderung eskaliert an den Owner. Der Build-Brief #1448 enthält das als stehende Entscheidung 6 des Owners, mit dem Design in blueprints/SC-3.md, blueprints/SC-4.md und blueprints/SC-16.md seines Pakets.

3. Das Question-Gate und das Rückschreiben in decisions.yaml

Abschnitt betitelt „3. Das Question-Gate und das Rückschreiben in decisions.yaml“

Was die Schleife braucht. Ein Agent, der auf eine echte Lücke stößt, fragt, statt zu raten. Das Item parkt, ohne einen Slot zu halten, der Owner antwortet auf irgendeiner Oberfläche, das Item läuft mit der Antwort weiter, und die Antwort wird über einen Pull Request ein Eintrag in decisions.yaml.

Heute. question.ask funktioniert: eine Frage von bis zu 4.096 Bytes mit bis zu 8 Optionen (server/crates/sc-svc-exec/src/question_ask.rs:40,44), ein Warten von bis zu 600 Sekunden (:36), beantwortet im Web-Eingang, auf der Telegram- oder Discord-Karte oder durch den Koordinator, der den Task delegiert hat. Eine deferred-Frage kehrt sofort zurück und hält die Antwort als dauerhafte Mailbox-Nachricht fest (server/crates/sc-svc-exec/src/mailbox/question.rs), die eingereiht wird und nie einen beendeten Task wiederbelebt (ADR 0074 D6). Was für die Schleife fehlt: Der Backlog hat keinen Wartezustand — seine sieben Zustände sind classified, queued, in_progress, in_review, done, blocked und needs_info (server/crates/sc-persistence/src/models/backlog.rs:93) —, eine geparkte Frage hält also ihren Nebenläufigkeits-Slot; ein Question-Gate hat keine Frist (timeout_policy: Hold, server/src/app_d1_tail_ports.rs:174); und nichts schreibt eine Antwort ins Issue oder ins Repository.

Geplant (SC-10, mit SC-20 Anforderung 7). Ein Park-Modus, der das Item nach awaiting_answer verschiebt, den Lauf nach einer Übergabenotiz beendet und den Slot freigibt; die Antwort stellt das Item mit Frage, Antwort und Branch als Wiederaufnahme-Kontext wieder ein — durch den normalen Gate-Stapel des Dispatchers, die Antwort selbst startet also weiterhin nichts. Eine Frist pro Projekt mit einer Standardaktion. Hat das Projekt eine Spec-Quelle, erzeugt die Antwort einen decisions:-Eintrag, der auf die Frage verweist, geliefert entweder im nächsten Implement-Pull-Request des Items oder als eigener Koordinator-Pull-Request — nie direkt auf den Standard-Branch gepusht.

Was die Schleife braucht. Designentscheidungen werden gebündelt vor der Arbeit beantwortet: ein Brief pro Domäne, jedes Element mit seinen Optionen, einer empfohlenen Option, der Begründung und Entwürfen (Tabellen, Diagramme, Vorher-nachher-Screenshots, Prototypen). Die Empfehlung ist der Bequemlichkeit halber vorausgewählt, aber eine vorausgewählte Option zählt erst als Antwort, wenn der Owner sie bestätigt — pro Element oder mit „alle offenen Empfehlungen übernehmen”. Die Übergabe wird verweigert, solange ein blockierendes Element offen ist. Antworten werden per Pull Request in decisions.yaml geschrieben.

Heute. Nichts. question.ask ist der einzige strukturierte Eingabekanal für Menschen, eine Frage nach der anderen. Der erste Spec-Pilot (bw-fm27, Clubfinanzen, 26 Entscheidungen) wurde auf einer Fragebogenseite außerhalb von SupaCloud beantwortet und von Hand ins Repository übertragen.

Geplant (SC-29 v2; sein Brief ist blueprints/SC-29.md im Paket von Issue #1448). Eine Brief-Seite mit Fortschritt, Zustand pro Element (open, as recommended, changed), elf Elementtypen von single_choice bis visual_signoff, ein Katalog von Entwurfsarten, Erzeuger (ein MCP-Werkzeug zum Veröffentlichen, Capture-Integration, automatische Briefs für einen Spec-Pull-Request, der proposed-Entscheidungen hinzufügt) und Senken — repo_file für decisions.yaml, issue, memory, run (geparkte Läufe freigeben) und webhook.

Was die Schleife braucht. Nichts wird gemergt, bevor nicht jeder Pflicht-Check des Ziel-Repositorys auf demselben Head-SHA grün ist — die CI des Projekts, sein Spec-Gate und der Status gate-class, den nur eine Owner-Freigabe grün macht — plus das Audit und die erforderlichen Review-Slots.

Heute. „Grün” heißt, dass der Task des unabhängigen Auditors fertig ist und das visuelle Gate bestanden oder übersprungen wurde: approve_and_complete dokumentiert gates_green als genau dieses Urteil und berechnet es nie neu (server/crates/sc-svc-orchestration/src/backlog/complete.rs:202-213). Kein Commit-Status wird je gelesen — server/crates/sc-forge/src/git/ci.rs ist ein Platzhalter. Unter full_auto hat die Merge-Entscheidung keinen Rückfall für sensible Pfade (complete.rs:161), und bei Autonomiestufe 100 ist die Merge-Obergrenze full_auto (server/crates/sc-svc-tenancy/src/autonomy/policy.rs:180-181), also entscheidet die eigene Merge-Policy des Projekts. Der Merge selbst ist ein Merge-Commit (server/crates/sc-forge/src/git/forgejo_pulls.rs:174); ein Repository, das nur Squash-Merges erlaubt, lehnt ihn ab, und ein geschützter Branch mit Pflicht-Checks lehnt einen Merge ab, dessen Checks nicht grün sind — in beiden Fällen bleibt das Item im Review, und nichts versucht es erneut.

Geplant (SC-1, mit SC-24 für den Merge-Stil). Pflicht-Status aus dem Branch-Schutz oder einer Projekt-Überschreibung sind eine zwingende Gate-Eingabe für jede Merge-Policy und jede Autonomiestufe; ein Merge-Gate-Ledger mit dem Schlüssel Item, Runde, Gate, Slot und Head-SHA; ein Watch-Tick, der bei Grün mergt und einen roten Check mit dem fehlschlagenden Kontext an den Umsetzer zurückgibt; menschliche Kontexte wie gate-class, die den Owner einmal benachrichtigen und ohne Frist warten — ein ausstehender Gate-Status heißt Warten auf Freigabe, nie ein CI-Fehler zum Nacharbeiten (SC-5); der Merge auf den auditierten SHA festgelegt; klassifizierte Wiederholungen.

Was die Schleife braucht. Das Spec-Format ist ein Produktvertrag: ausgeliefert, versioniert und drift-geschützt wie die anderen Verträge von SupaCloud, serverseitig als zweite Prüfung validiert, von der Anforderung bis zur Evidence nachverfolgt und in der Web-Oberfläche lesbar.

Heute. spec.get liefert genau vier Plattformverträge — openapi_public, workflow_schema, mcp_catalog und command_catalog (server/crates/sc-svc-mcp/src/mcp/spec_corpus.rs:24-29). Es gibt keinen Code für Anforderungen oder EARS. Das Crate sc-spec ist die Workflow-Spec (der WorkflowSpec-DTO-Baum), ein Crate für Anforderungs-Specs braucht also einen anderen Namen.

Geplant (SC-20). Das Format der Referenzimplementierung unverändert als Delivery-Spec-Format übernehmen — Version 0.2, deren Projektprofil es erst möglich macht, dass ein ausgelieferter Vertrag zu Projekten mit unterschiedlichen Katalogen, ID-Formen und Einheiten passt; es über spec.get veröffentlichen, generiert und in einem Drift-Test byteweise verglichen; ein Blatt-Crate sc-reqspec mit dem typisierten Format und seinen Strukturprüfungen; spec_sources, ein spec-Gate (off, advisory, required) und ein decision_mode pro Projekt; ein Traceability-Bericht von der Anforderung bis zur Evidence; Drift-Markierung abhängiger Items, wenn eine gemergte Änderung eine Klausel bearbeitet; eine nur lesende Spec-Ansicht. Ein OpenSpec-Import/-Export-Adapter folgt später; keine Laufzeit hängt von OpenSpec-Werkzeugen ab.

Manche Regeln hängen bewusst nicht von SupaCloud ab:

  • Die Gate-Klassen werden durch einen Pflicht-Status im Repository des Projekts durchgesetzt, weil der Autonomieregler die Merge-Obergrenze von SupaCloud auf full_auto heben kann. Die Merge-Policy von SupaCloud darf nur einschränken, was dieser Status erlaubt. In der Referenzimplementierung ist das gebaut und in Betrieb (gate-class, WI-SPEC-007, gemergt am 22.09.2026); der Abschnitt darunter beschreibt es, wie es läuft.
  • Das Spec-Gate und die Work-Item-Gates laufen in der eigenen CI des Projekts. Das spec-Gate von SupaCloud ist eine zweite Prüfung, kein Ersatz.
  • Die Verträge und Specs sind die Quelle der Bereitschaftsregel. SupaCloud liest sie; es hält keine zweite Kopie des Arbeitsstands.

Der Status gate-class, wie er in der Referenzimplementierung läuft

Abschnitt betitelt „Der Status gate-class, wie er in der Referenzimplementierung läuft“

Die Regeln liegen in einer Datendatei (tools/qa/gate_classes.yaml, selbst Klasse G2) und einem Prüfer (tools/qa/check_gate_classes.py), Pfad für Pfad dokumentiert auf der Gate-Klassen-Seite des Repositorys. Jede Klasse nennt ihren Freigebenden: owner für G1 Spieldesign, G2 Architektur und Verträge, G3 Art Direction und ersten Eindruck, G4 sensible Themen und G5 Release und Recht; security_review für S1 neue Abhängigkeiten, S2 CI-Workflows und S3 Security-Werkzeuge, Policies und Gate-Konfiguration.

Was er setzt. Einen Commit-Status mit dem Kontext gate-class auf dem Head-Commit des Pull Requests: success, wenn keine Klasse greift oder jede greifende Klasse für genau diesen Head-Commit freigegeben ist (die Beschreibung nennt, wer welche Klasse freigegeben hat), pending, wenn eine Klasse wartet — mit jeder Klasse, ihrem ersten Pfad oder ihren neuen Paketnamen und dem, auf den gewartet wird —, und error, wenn kein ehrliches Urteil möglich war, was wie pending blockiert. Es ist ein erforderlicher Status auf dem main der Referenzimplementierung, neben ihren drei core-ci-Kontexten (core-ci / python (pull_request), core-ci / format (pull_request), core-ci / dotnet (pull_request)); ein wartender Pull Request kann also weder von einer autonomen Schleife noch über die API von einem Konto ohne Adminrechte gemergt werden.

Wann er läuft. pull_request_target (opened, synchronize, reopened, edited), also bei jedem neuen Head und jedem Umhängen; pull_request_review (submitted, edited); und issue_comment (created, edited, deleted) an einem Pull Request, aber nur, wenn der Kommentar ein /approve-gates-Befehl ist oder war. Andere Kommentare starten nichts. Klassenkarte und Prüfer kommen immer vom Basis-Branch — bei einem Kommentar vom Default-Branch —, ein Pull Request kann die Regeln, nach denen er beurteilt wird, also nicht lockern; der Head wird nur als Daten geholt.

Wie eine Klasse freigegeben wird.

  • Eine Owner-Klasse wird durch ein zustimmendes Review des Head-Commits durch das Owner-Konto freigegeben oder durch den Pull-Request-Kommentar /approve-gates <sha> des Owners, der genau diesen Head-Commit nennt (vollständige SHA oder ein Prefix aus mindestens 12 Hex-Zeichen; die wartende Beschreibung nennt das zu verwendende Prefix).
  • Ein bearbeiteter Kommentar zählt nicht, was auch immer danach darin steht — jedes Konto mit Schreibrecht kann jeden Kommentar bearbeiten, ein bearbeiteter Text lässt sich also nicht als der des Owners belegen. Stattdessen einen neuen Kommentar schreiben. Einen Kommentar zu bearbeiten oder zu löschen bewertet den Pull Request neu und zieht damit eine Freigabe zurück, die nicht mehr da ist.
  • Eine Security-Review-Klasse wird durch ein zustimmendes Review des Head-Commits von einer gelisteten Reviewer-Identität — der automatisierten Security-Review-Bahn — oder durch den Owner freigegeben, der immer freigeben kann. Ein Änderungswunsch dieses Reviewers eskaliert jede Security-Review-Klasse des Pull Requests an den Owner, der sie dann allein freigibt.
  • Eine Freigabe gilt nur für den Commit, den sie nennt. Ein neuer Push wird von vorn klassifiziert, verworfene und als veraltet markierte Reviews zählen nicht, und ein späterer Änderungswunsch des Owners hält jede Klasse wieder — auch die, die ein Reviewer freigegeben hatte.

Zwei ehrliche Grenzen. Forgejo lehnt die Freigabe durch den Autor eines Pull Requests ab; genau deshalb gibt der Owner eigene Pull Requests per Kommentar frei und nicht per Review — der Kommentarweg ist ein Ausweg um eine Forge-Regel herum, kein zusätzliches Privileg. Und ein Instanz-Admin kann weiterhin am Branch-Schutz vorbei force-mergen, was die Regel auch sagt; das ist die Notausstiegsluke des Owners und ein Grund, Instanz-Admin-Zugänge von Agenten fernzuhalten. Im selben Sinn: Jedes Konto und jeder Workflow mit Schreibrecht kann einen Commit-Status mit beliebigem Kontext setzen. Das Gate hält den autonomen Merge-Weg zuverlässig auf — es ist keine Verteidigung gegen einen Schreiber, der gate-class absichtlich fälscht.