rig-epic — Integration-Branch-Workflow
Für mehrteilige Arbeitspakete, bei denen das direkte Einspielen jedes Teils auf den Haupt-Branch den Laufzeitvertrag vorübergehend brechen würde, werden Child-PRs auf einem gemeinsamen Integration-Branch gestapelt und dieser Branch am Ende als ein PR zusammengequetscht in den Haupt-Branch überführt. Jeder Child-PR wird als der Schritt, der er tatsächlich ist, reviewed; die trunkgebundene Auslieferung ist ein einziger squasht-basierter Rebase.
Konfiguration
Liest .rig/config.json (Standardeinstellungen in Klammern):
tracker.provider—linear|github|none(none). Wie Eltern/Kind-Elemente gespeichert werden.none→ Elemente leben nur in der Epic-Zustandsdatei (unten); keine Tracker-Aufrufe.tracker.team/tracker.project/tracker.ticketPrefix/tracker.githubIntegration.vcs.baseRef(origin/main),vcs.defaultBranch(main),vcs.protectedBranchMergeQueue(false).sourceScope[0]— wo währendplanerkundet werden soll.agents.architect/agents.reviewer(Standardrig-<roll>), für dasreview-Panel mit frischem Kontext.
Delegiert an /rig-task (pro Child), /rig-worktree (Checkouts), /rig-review
/rig-review fix(das kombinierte Diff-Review),/rig-tidy(optional).
Epic-Zustandsdatei (ersetzt externen Speicher)
Jedes aktive Epic wird in einer repo-lokalen JSON-Datei unter
.rig/epics/<integrations-branch>.json verfolgt:
{
"parent": "ABC-42 oder ein Slug bei tracker=none",
"parentTitle": "…",
"integrationBranch": "abc-42-<slug>",
"whyEpic": "welche Kinder sich überschneiden und warum",
"children": [
{ "id": "ABC-43", "title": "…", "blockedBy": [], "branch": null, "status": "todo|merged" }
]
}
Dies ist die einzige Quelle der Wahrheit, die next/run/review/finish/prune
lesen. Füge .rig/epics/ zu .gitignore hinzu (es ist transitorischer Koordinationszustand).
Eltern-Inferenz (wenn <PARENT> weggelassen wird): Wenn genau eine
.rig/epics/*.json existiert, verwende sie; wenn null oder viele, frage nach.
Intent-Banner: Jeder Aufruf MUSS als erste Zeile einen Hinweis drucken – Modus, auf welchen Branch PRs zielen, was es nicht tun wird:
rig-epic: <subcommand> — <action>. PRs target <branch>. Will not <thing>.
status (Standard, nur Bericht)
Lies die Epic-Zustandsdatei(en). Bericht: Integration-Branch + Commits vor
vcs.baseRef; offene Child-PRs (gh pr list --base <integrations-branch>) und
ihr Zustand; der Tracker-Status jedes Kindes (falls ein Tracker vorhanden);
übriggebliebene zusammengeführte/gelöschte Worktrees (schlage /rig-epic prune
vor); und eine einzeilige Empfehlung (open child PR X, ready for /rig-epic next, oder ready for /rig-epic finish). Ändere
nichts; starte nichts.
plan <FEATURE>
Zerlege ein Feature in ein Eltern-Element + 3–8 Kinder, schreibe die
Zustandsdatei, dann verketten mit start.
Verwende dies nur, wenn die Arbeit wirklich episch geformt ist (Kinder
überschneiden sich – mindestens ein Kind hängt vom teilweisen Abschluss eines
anderen ab). Wenn die Elemente unabhängig sind und jedes allein auf dem
Haupt-Branch landen kann, stoppe und sage dem Benutzer, /rig-sprint plan
stattdessen auszuführen – gleiche Zerlegung, kein Integration-Branch.
Vorgehen
- Kontext lesen. Produkt-/Spezifikationsdokumente, falls das Projekt sie hat
(im Zweifelsfall fragen); die Codebasis erkunden (
sourceScope[0]), um zu sehen, was existiert. Wenn ein Tracker konfiguriert ist, suche zuerst nach fast-identischen Elementen. - Auf Epic überprüfen (gemäß dem Überschneidungstest oben). Wenn nicht →
an
/rig-sprint planweiterleiten. - Elternelement erstellen.
tracker: linear/github→ das Elternelement erstellen (Team/Projekt aus Konfiguration); Beschreibung umfasst Übersicht, warum es ein Epic ist, und die geplanten Kinder.tracker: none→ das Elternelement ist ein Slug + Titel, nur in der Zustandsdatei aufgezeichnet.
- Jedes Kind erstellen mit seinen Abhängigkeitskanten.
- Klein genug für eine Agentensitzung (1–3 Dateien); konkret, testbare Abnahmekriterien; Grundlagenarbeit zuerst.
blockedByfür jede echte Abhängigkeit aufzeichnen – dies ist, wasnextliest, um das nächste nicht blockierte Kind auszuwählen. Ohne diese Angabe fällt die Auswahl auf die Deklarationsreihenfolge zurück und überschneidende Epics werden falsch behandelt.- Tracker-Modus: native Eltern/blockedBy-Beziehungen des Trackers setzen
und diese in der Zustandsdatei spiegeln.
none: nur Zustandsdatei.
- Zusammenfassungstabelle anzeigen (ID · Titel · Hängt ab von).
- Verkettung mit
start <PARENT>–planist planen-und-starten; nicht anhalten, um zu fragen. - Nach
startanhalten. Den Integration-Branch, die Kinder und den nächsten Schritt melden (/rig-epic nextfür einen,/rig-epic runfür die Schleife). Niemals automatischrunstarten – die Ausführung erfolgt explizit durch Opt-in.
start <PARENT>
Vorbereitung: git fetch origin; bestätigen, dass das Elternelement und
mindestens ein Kind existieren (im Tracker oder als Argumente für none).
- Integration-Branch-Name:
<parent-slug>-<titel-slug>(Kebab, z. B.abc-42-agent-as-definition). - Integration-Branch von
vcs.baseRefaus erstellen ohne lokalen Checkout:
Nicht destruktiv. Wenn der Branch bereits existiert, belasse ihn (niemals überschreiben – könnte laufende Arbeit zerstören).git fetch origin git push origin <vcs.baseRef>:refs/heads/<integrations-branch> .rig/epics/<integrations-branch>.jsonschreiben (Schema oben) mit dem Elternelement, warum-Epic und jedem Kind +blockedBy. Dies bewirkt, dass jedes/rig-task <child>den Integration-Branch anstelle des Haupt-Branch als Ziel verwendet.- Wenn ein Tracker konfiguriert ist, füge jedem Kind eine Notiz hinzu:
"Integration-Branch: target
<integrations-branch>, nicht der Haupt-Branch", sodass der nächste Agent dieses Skill nicht erneut lesen muss, und stelle sicher, dass das Elternelement den Status In Bearbeitung erhält (adaptiv: verschiebe es nur, wenn es nicht bereits gestartet ist; verschiebe, wenn eine laufende Integration dies bereits getan hat). Kinder erhalten ihren eigenen Status In Bearbeitung durch Schritt 1 ihres/rig-task. - Sitzung benennen
"EPIC: <Elterntitel> (<Eltern>)"überscripts/set-session-name.sh(nur für Claude-Code; andernorts keine Operation), sodass die Hintergrundjob-Liste das Epic anzeigt. Kinder setzen ihre eigenenFEAT:/CHORE:-Namen mit--skip-if-prefix "EPIC:", sodass dieses Epic-Label oben bleibt. - Bericht über den Branch, die Kinder und den nächsten Schritt.
next (einzelnes Kind)
- Aktiven Integration-Branch auflösen (einer erwartet; bei vielen nachfragen).
Wenn die Sitzung nicht bereits
EPIC:-benannt ist (d. h.nextdirekt aufgerufen, nicht überstart), benenne sie"EPIC: <Elterntitel> (<Eltern>)"(nur Claude-Code). - Nächstes nicht blockiertes Kind auswählen: das erste nicht erledigte Kind,
dessen
blockedByalle in den Integration-Branch eingefügt wurden. Die Auswahl + Begründung im Banner angeben. - Sicherstellen, dass das vorherige Kind eingefügt wurde. Mit
--auto-merge(Schritt 4) wird der PR jedes Kindes in den Integration-Branch eingefügt, sobald CI besteht, sodass die Integrationsspitze automatisch vorrückt – einfachgit fetch originund bestätigen. (Fallback für ein Kind, das ohne--auto-mergeausgeführt wurde: den Branch über seine Spitze vorspulen –git push origin origin/<vorheriger-kind-branch>:refs/heads/<integrations-branch>, was diesen PR automatisch als MERGED schließt. Sicheres Wiederholen.) /rig-task <CHILD> --base <integrations-branch> --auto-mergeausführen (--spec-clearedhinzufügen, wenn die vorab geladene Spezifikationsprüfung vonrundie Spezifikationen bereits freigegeben hat) –--basebewirkt, dass der Worktree-Branch des Kindes vom Integration-Branch abzweigt und sein PR auf diesen zielt;--auto-mergebewirkt, dass das Kind auf seinem eigenen PRgh pr merge --squash --autoaktiviert, sobald sein Review sauber ist, sodass CI es in den Integration-Branch einfügt (immer squash – nicht rebase-merge; viele Repos erlauben dies nicht. Wenn der Integration-Branch keine erforderlichen Prüfungen hat, wird das Kind direkt eingefügt). Einmal ausführen (start→finish); es gibt eine einzelne Ergebniszeichenkette für das Merge-Gate zurück.- Merge-Gate – nur
cleanist merge-grün:clean→ das Kind hat Auto-Merge aktiviert, also landet sein PR, wenn CI besteht. Warten Sie: Pollgh pr view <N> --json state(~60s, bis zu ~30min), bisMERGED, danngit fetch originund bestätigen, dass die Spitze vorgerückt ist. Das Kindmerged+ seinen Branch in der Zustandsdatei aufzeichnen und sicherstellen, dass das Kind-Ticket auf Erledigt gesetzt ist (adaptiv – nur verschieben, wenn es nicht bereits Erledigt ist; verschieben, wenn eine laufende Integration es geschlossen hat). Wenn CI fehlschlägt / es nie eingefügt wird → als nicht-clean behandeln.- alles andere (
actionable/timeout, oder ein im Tracker geparkter Zustand) → das Kind hat Auto-Merge nicht aktiviert; anhalten. Das Ergebnis, die PR-URL und die Zusammenfassung des Reviewers anzeigen. Auf den Benutzer warten; keinen geparkten Review wiederholen.
next macht genau ein Kind. Verwende run für die Schleife.
run [--advisor]
Vorab geladene Spezifikationsprüfung – einmal, vor der Schleife. Überprüfe alle Spezifikationen der Kinder gemeinsam, im Voraus, anstatt Blocker während der Laufzeit ein Kind nach dem anderen zu entdecken. Ein Kind, das bei einer Spezifikationsfrage pausiert, blockiert das gesamte Epic (und bei paralleler oder dauerhafter Ausführung kann ein pausiertes Kind den Batch vollständig zum Scheitern bringen), also löse die Spezifikationen, bevor irgendein Kind mit dem Coden beginnt:
- Verteile
agents.architect+agents.qaüber jede Spezifikation jedes Kindes, gelesen gegen den Integration-Branch; jeder gibt seine Blocker zurück. - Konsolidiere zu einer Blockerliste und löse sie einmal – kläre im Tracker oder entscheide mit dem Benutzer. Dies ist der einzige Spezifikations-Entscheidungspunkt des Epics.
- Dann führe jedes Kind mit seinem eigenen Spezifikations-Gate vorab
freigegeben aus:
/rig-task <CHILD> --base <integrations-branch> --auto-merge --spec-cleared, sodass kein Kind bei einer bereits beantworteten Frage erneut pausiert.
Dies ist der vor dem Codieren durchgeführte Spezifikationsdurchlauf; das
kombinierte Diff-Review review (unten) ist der nach dem Merge
Code-Durchlauf – unterschiedliche Gates.
--advisor (unbeaufsichtigt). Entscheide über dieses vorab geladene Gate
mit einem Advisor-Durchlauf anstelle eines Menschen: Ein delegiertes
agents.architect-Review liest die Architekten- + QA-Spezifikationen und
entweder fährt fort mit synthetisierten, pro Kind gerichteten Anweisungen
(wörtlich an den Coder jedes Kindes weitergegeben) oder hält an mit einem
Blockierungsbericht, der benennt, was ein Mensch entscheiden muss. Kein Mensch
wartet, also läuft das Epic autonom bis zu den Child-PRs; ein echter Blocker
stoppt es dennoch, anstatt sich auf eine schlechte Spezifikation zu
verzweigen. (Der gepaarte Smithers-Dauer-Workflow implementiert dies mit einem
günstigen Modell – dem "Fable Advisor" –, sodass gestartete Epics nie am Gate
parken.)
Dann Schleife next, bis kein nicht blockiertes Kind mehr übrig ist:
while an unblocked child exists:
run /rig-epic next # children run --spec-cleared (spec was front-loaded)
if it stopped without merging (outcome ≠ clean) → stop, hand back
else → re-evaluate unblocked children
Wenn die Warteschlange leer ist, melde "Epic bereit für /rig-epic finish."
review [<PARENT>]
Ausführen, nachdem das letzte Kind in den Integration-Branch eingefügt wurde,
vor finish. Das Per-PR-Review (/rig-review innerhalb jedes /rig-task)
sieht jedes Kind isoliert; dies sieht die kombinierte Form und die
Vereinfachung, die erst sichtbar wird, wenn alles eingefügt ist.
Sub-Agenten mit frischem Kontext (Eingabe = der squashte Diff + Child-PR-Titel)
können die auswendig gelernten Rationalisierungen des Implementierers nicht
übernehmen.
Vor prune ausführen – die Review-Sub-Agenten benötigen einen
funktionierenden Checkout; verwende einen Child-Worktree, falls noch einer
existiert (vermeidet eine frische Installation + erneutes Symlinking der
Umgebung).
- Integration-Branch auflösen;
git fetch origin. - Integration-Branch-Worktree sicherstellen (
$WT). Verwende einen zusammengeführten Child-Worktree, der auf die Integrationsspitze vorgezogen wurde, wieder, sonst erstelle einen mit/rig-worktree(--base <integrations-branch> --reuse). - Drei Sub-Agenten parallel verteilen (eine Nachricht, drei
Agent-Aufrufe), jeder mitcdin$WTund ausgecheckter Integrationsspitze:- Linse 1 – Vereinfachung (
agents.architect): Diffgit diff <vcs.baseRef>...HEAD; Child-PR-Liste übergh pr list --base <BR> --state merged. Auftrag: Abstraktionen finden, die zusammengelegt werden können; Helfer, die ein PR hinzugefügt hat, die die endgültige Form eines anderen PRs überflüssig gemacht hat; Konfigurationsknöpfe, die niemand setzt; Codepfade, die das kombinierte Diff tot gemacht hat; Typen mit einem Aufrufer. Konkrete Löschungen/Zusammenlegungen, Datei:Zeile, höchste Auswirkung zuerst. Korrektheit überspringen. - Linse 2 – Cross-PR-Korrektheit (
agents.reviewer): Durchlaufe den Review-Musterkatalog des Projekts (review.patternsFile) gegen das kombinierte Diff. Das Per-PR-Review wurde bereits ausgeführt; fange Interaktionen, die nur in der eingefügten Form sichtbar sind (PR-A's Helfer vs. PR-D's veralteter Aufrufer; PR-B hat einen Knopf entfernt, den PR-F noch liest). P0/P1/P2 mit Datei:Zeile + Kategorie. - Linse 3 – Toter Code und veraltete Referenzen (
agents.reviewer): Für jedes Symbol, das der Diff hinzugefügt hat, wird es woanders aufgerufen? Für jedes Symbol, das entfernt wurde, durchsuche den Baum (Workflows, Manifeste, IaC, Skripte, Docs) nach Restverweisen. Bericht mit Datei:Zeile.
- Linse 1 – Vereinfachung (
- Konsolidieren – deduplizieren, eine P0/P1/P2-Liste gruppiert nach Linse erstellen, Anzahl ausgeben.
- Triage:
- 0 Einträge →
clean — bereit für /rig-epic finish, stoppen. - Ergebnisse → frage über
AskUserQuestion:jetzt anwenden/überspringen und trotzdem abschließen(auf Folgeaufgaben herabstufen) /pausieren. Beijetzt anwenden/rig-review fix --source localin$WTausführen (startetagents.coder, erneutes Review bis sauber), Commiten +git push origin <integrations-branch>,revieweinmal erneut ausführen, um Konvergenz zu bestätigen.
- 0 Einträge →
- Ergebniszeichenkette (für
finish):clean — …/applied — …/paused — ….
finish [<PARENT>] [--merge]
Squasht den gesamten Integration-Branch in einen einzelnen PR zum Haupt-Branch. Standard: PR öffnen und anhalten – dies ist der eine PR, den man begutachten sollte.
review ist ein hartes Gate. finish führt immer zuerst review aus; der
Squash-PR öffnet sich nur bei clean oder applied. Bei paused anhalten und
warten.
review(Gate) inline ausführen; basierend auf seinem Ergebnis verzweigen (clean/applied→ fortfahren;paused→ anhalten und ausstehende Ergebnisse ausgeben).- Aktualisieren und ggf. rebasen.
git fetch origin; listegit log <vcs.baseRef>..origin/<integrations-branch> --oneline. Wenn der Haupt-Branch sich bewegt hat, den Integration-Branch zuerst auf ihn rebasen (git rebase <vcs.baseRef>auf einer lokalen Kopie, danngit push --force-with-lease origin <lokal>:<integrations-branch>). - Den finalen PR öffnen auf
vcs.defaultBranchmit einem Titel, der auf das Elternelement verweist, und einem Rumpf, der alle Kinder zusammenfasst. In einem Tracker mit einem Schlusswort (Fixes <ELTERN>/Closes #<n>), dieses einschließen, damit das Elternelement automatisch geschlossen wird