Einen PR öffnen
Einen PR gut zu öffnen ist ein Recherche-Problem, bevor es ein Git-Problem ist. Ein Reviewer entscheidet im ersten Bildschirmausschnitt, ob der Autor das Repo kennt – die Titel-Grammatik, die Körperform, die Commit-Betreffe signalisieren es alle –, also ist die Arbeit: Lerne, was die Maintainer dieses Repos schreiben, und schreibe dann das.
Wähle zuerst die Tiefe
Express ist für „öffne einfach den PR“, „ship es einfach“, „bring es rein“ – und für jede Änderung, die klein genug ist, dass die Recherche mehr kosten würde als die Überprüfung, die sie spart. Orientieren, schreiben, ausliefern, die Überwachung übergeben. Überspringe den Stil-Scout und seine Karte, die Stimmenkalibrierung und das Prosa-Gate. Frage nicht, ob Express gewünscht ist: Die Formulierung hat es bereits gesagt, und es zu bestätigen ist die Verzögerung, die der User vermeiden wollte.
ccx vcs lane --json
ccx vcs diff
ccx vcs ship --no-watch --pr-title-file "$TITLE" --pr-body-file "$BODY"
Der Body sagt immer noch, was sich geändert hat und warum, in der Vorlage des Repos, falls vorhanden, und der Titel entspricht immer noch der Grammatik der letzten paar gemergten PRs – ein gh pr list --state merged --limit 5 --json title Lesevorgang, kein Scout. Express lässt die Recherche weg, niemals den Body: Ein PR ohne Body ist das Eine, was keine Spur ausliefert.
Voll ist der Rest dieser Datei und rechtfertigt seine Kosten auf einem Repo, das du nicht besitzt, bei einer Änderung, von der ein Maintainer überzeugt werden muss, oder beim ersten Mal, dass du irgendwo einen PR öffnest. Auf einem fremden Repo sind die Konformitäts- und Höflichkeitsdurchläufe selbst im Express-Modus nicht optional – ein Gast, der sie überspringt, verschwendet die Hin- und Rückreise des Maintainers, nicht seine eigene.
Orientieren
Der Pfad ist hier wichtig: Drei Befehle, deren benannte Ausgabe alles Nachgelagerte referenziert.
ccx vcs lane --json # Lane, Branch, Trunk, Dirtiness, github.mine, Downstack-PRs und welche keine Bodies haben
gh repo view --json isPrivate,owner,viewerPermission,pullRequestTemplates,nameWithOwner,defaultBranchRef
ccx vcs guidelines # CONTRIBUTING, PR-Vorlage, Verhaltenskodex, Issue-Konfiguration – gibt den Kartenpfad aus
Dann ccx vcs diff für die Änderung selbst.
ccx vcs lane meldet die Lane – es wählt sie nicht aus, und du tust es auch nicht. ccx vcs ship wählt zum Zeitpunkt des Auslieferns zwischen jj, git oder gt, und ein Repo, das der User nicht kontrolliert, fällt stillschweigend aus der gt-Lane heraus. Schreibe also nichts, das eine Lane voraussetzt, bevor ship eine meldet. github.mine ist das Eigentumsurteil; der Test dahinter und alles, was von mine: false abhängt, befinden sich in reference/oss.md. Lies die Karte, die ccx vcs guidelines geschrieben hat, und trenne dann harte Anforderungen von Präferenzen – reference/guidelines.md enthält die Hinweise und die gh api-Fallbacks für ein Repo, das nichts veröffentlicht.
Lerne den Hausstil
Der Hausstil lebt in einer Karte auf der Festplatte, einmal pro Repo gescoutet und gecacht:
bash "${CLAUDE_PLUGIN_ROOT}/scripts/pr-cache.sh" status <owner/name> # fresh | stale:<grund> | missing
bash "${CLAUDE_PLUGIN_ROOT}/scripts/pr-cache.sh" path <owner/name> # gibt das Cache-Verzeichnis aus
fresh benötigt keinen Scout – lies die Karte und fahre fort. stale oder missing → starte den Scout, einmal pro Repo pro Lauf:
Agent(subagent_type: "open-pr:pr-style-scout",
prompt: "repo: <owner/name>\ncache: <dir>\nviewer: <gh login>")
Der Scout sammelt Stichproben aktueller gemergter PRs, filtert Bots, KI-geschriebene PRs und – auf einem fremden Repo – die des Betrachters selbst heraus und schreibt die Karte in das Cache-Verzeichnis. Er gibt einen Pfad, eine kurze Zusammenfassung und eine Konfidenz zurück – lies die Karte, die er geschrieben hat, nicht seine Erzählung.
Die Karte führt ihre Stichprobengröße und eine konfidenz pro Achse, weil die Filter, die die Stichprobe menschlich halten, sie auch verkleinern. Titelgrammatik und Körperstruktur sind Konventionen – sie gelten bei jeder Stichprobengröße. Review-Antwort-Ton und Prosa-Register basieren auf weniger Signalen: Bei confidence: low sind sie eine Tendenz, keine Regel, und die PR-Vorlage und Richtlinien haben mehr Gewicht. Eine aus drei Stichproben abgelesene Konvention beschreibt diese drei. Cache-Layout, Kartenschema und Veralterung befinden sich in reference/style-cache.md.
Kalibriere die Stimme
Wenn der User ein lokales wlm-Profil hat, leihe dir die Teile seiner Stimme, die das Format überleben:
wlm profile list
wlm -p <profile> stylecard show # -p kommt vor dem Unterbefehl und ist nicht optional
Die wlm-Karte wurde für lange Blog-Prosa gebaut: Die „Nie“-Liste und die Wortwahl übertragen sich vollständig, der Ton zur Hälfte, Länge und Eröffnungen gar nicht. Die vollständige Übertragungstabelle und der Fallback ohne Profil befinden sich in reference/voice.md. Wo sich die Karte des Repos und die Stimmkarte widersprechen, gewinnt das Repo – du bist ein Gast in seinem Format.
Repos, die du nicht kontrollierst
github.mine: false ändert das Register und fügt vor dem Schreiben zwei Durchläufe hinzu (reference/oss.md):
- Das Höflichkeitsregister – direkt über die Änderung, respektvoll gegenüber der Entscheidung: Zahlen tragen die Behauptungen, der Maintainer behält die Entscheidungen, die ihm gehören.
- Standardkonformität – gehe
ccx vcs diffgegen die Richtlinienkarte und die Checkliste durch: Umfang, Stil, Tests, Docs, Commit-Hygiene, Diff-Größe gegen die gemergte PR-Norm des Repos. Jede Abweichung ist eine Korrektur oder ein Satz im Body, der die Abweichung eingesteht. - Issue-First – wenn die Richtlinienkarte ein Issue als harte Anforderung markiert, suche vor dem Öffnen:
gh issue list --repo <slug> --search "<keywords>" --state all. Kein Treffer → skizziere das Issue, lege dann den Entwurf dem User mitAskUserQuestionvor – öffnen wie entworfen / zuerst bearbeiten / ein bestehendes Issue verlinken / die Anforderung absichtlich überspringen – und handle nach seiner Wahl. Ein Issue zu öffnen veröffentlicht unter dem Namen des Users auf dem Projekt eines anderen; es zu entwerfen nicht.
Schreiben
Titel, Body und Commit-Betreffe folgen der Stilkarte mit ihrer angegebenen Konfidenz; die PR-Vorlage, falls vorhanden, ist das Skelett des Bodys. Eine Zahl, wo ein Adjektiv sonst die Änderung bewerten würde: Ein Reviewer verifiziert „40 ms vom Kaltstart entfernt“ und verwirft „viel schneller“.
Schreibe den Body und den Titel in Dateien, niemals als Shell-Argumente – ein Body mit Backticks, $ oder einem Code-Block überlebt keine Kommandozeile intakt, und ein Titel wird dort für weniger abgelehnt (siehe Ausliefern):
BODY=$(mktemp)
TITLE=$(mktemp)
Der Body ist Prosa, also durchläuft er vor dem Ausliefern das Prosa-Gate: slop-cop check "$BODY" --lang=markdown, wobei die Flags triagiert werden, anstatt alle zu akzeptieren.
Commit-Nachrichten erhalten die gleiche Behandlung: Die Karte zeichnet die Betreffgrammatik dieses Repos, seine Länge und welche Trailer seine eigenen gemergten Commits tragen auf – gleiche diese Trailer und keine anderen. In einem Repo, dessen Historie kein Co-Authored-By: Claude oder Generated with Claude Code enthält, ist ein Trailer, der das Tooling ankündigt, die eine Zeile, die einen sorgfältigen PR als automatisiert erscheinen lässt, und Maintainer filtern danach; in einem Repo, dessen Historie sie enthält, ist das Behalten die Konvention.
Ein Stapel pro Sitzung
Verwandte Arbeit aus einer Sitzung geht in einen verketteten Stapel, niemals in unabhängige Geschwister vom Trunk – selbst wenn die Diffs nachweislich disjunkt sind. „Die Dateien überschneiden sich nicht“ ist kein Grund zum Aufteilen: Geschwister löschen die Review-Reihenfolge aus, die eine Kette angibt, und geben die Mid-Stack-Mechanik auf – ein Rebase trägt eine Änderung durch jeden Branch darüber, während Geschwister jeweils allein rebasen. Verkette in Abhängigkeitsreihenfolge, was konsumiert, über dem, was es konsumiert; eine noch in Bearbeitung befindliche Lane geht an die Spitze, damit die fertigen Branches darunter nie unter ihrem Änderungsaufkommen neu gerebased werden. Mechanik in reference/stack.md.
Ein PR ist eine funktionsgroße Arbeitseinheit. Folgearbeiten, Korrekturen und Review-Antworten sind Commits auf dem offenen PR, niemals ein gestapeltes Kind. Liefere sie mit ccx vcs ship aus, wobei --amend hinzugefügt wird, um sie in den Commit zu falten, oder --tip-only, wenn sich nur die Spitze eines Stapels geändert hat. Staple nur, wenn ein Elternteil landen muss, bevor andere Arbeit fortgesetzt werden kann, oder wenn das Review die Aufteilung benötigt. Pushe an kohärenten Checkpoints, niemals pro Bearbeitung, weil jeder Push den laufenden Build überschreibt und CI sowie die Review-Bots erneut ausführt. Pushe dennoch innerhalb der Stunde, da Origin das Backup ist.
Ausliefern
Die Flag-Kombination ist tragend:
ccx vcs ship --no-watch --pr-title-file "$TITLE" --pr-body-file "$BODY"
Schreibe den Titel in eine einzeilige Datei neben der Body-Datei und übergib --pr-title-file, niemals ein Inline---pr-title. Die Bash-Sandbox eines Worktree-isolierten Agenten lehnt jedes Argument ab, das ein Anführungszeichen mit dem Wort git oder einem Shell-Namen paart, wie GitHub's ... git, und ein Titel in einer Datei erreicht niemals die Kommandozeile. Ship übernimmt den Commit-Betreff aus diesem Titel und den Commit-Body aus dem PR-Body, daher wird -m nur für einen Betreff benötigt, der sich vom Titel unterscheidet.
--no-watch, weil die eingebaute Überwachung von Ship blockiert, bis CI abgeschlossen ist – genau dann, wenn du wartest, falsch, wenn die Überwachung gerade übergeben werden soll. Ship besitzt PR-Erstellung und -Aktualisierung in jeder Lane: Ein handgemachtes gh pr create daneben erzeugt einen PR, den die gt-Lane nicht mit ihrem eigenen Stapel in Einklang bringen kann.
Bei einem bereits offenen PR warnt Ship und behält den Titel und Body, den es hat, also trägt eine Änderung keine der beiden Flags, und ein PR, dessen Text geändert werden soll, benötigt --replace-pr-text.
Auf der gt-Lane kann eine Einreichung mehrere PRs erstellen, und jeder PR in der Einreichung, der noch keinen Body hat, bekommt einen. --pr-title-file und --pr-body-file wiederholen sich und gelten bereichsweise pro Branch (--pr-body-file <branch>=<pfad>; ein nackter Wert gilt für die Spitze); ccx vcs lane --json sagt dir, welche Downstack-PRs bodylos sind.
Eine Ablehnung ist eine Information, kein erneuter Versuch: nothing to commit bedeutet, dass eine frühere Auslieferung dies bereits gelandet hat; Ship wiederholt ein gt needs_restack selbst. Wenn Ship sich immer noch weigert, weil ein Branch von seinem Elternteil abgewichen ist oder der Trunk sich bewegt hat, führe ccx vcs stack submit aus (oder gib die Ablehnung wörtlich an den Besitzer des Stapels weiter, wenn eine andere Lane ihn besitzt) und führe Ship dann erneut aus.
Ship meldet den Branch, die PR-Nummer und URL sowie den Head-Sha. Die Übergabe benötigt alle vier.
Übergib die Überwachung
Löse ${CLAUDE_PLUGIN_ROOT} zum Zeitpunkt der Erstellung zum absoluten Pfad im Aufrufer auf und fülle poll: mit dem bereiten Befehl. Die Variable wird im Text dieses Skills substituiert; der Unteragent erhält sie nicht. Übergib den Satz nach poll: wörtlich, damit der Watcher das Skript bewaffnen kann, selbst wenn das Harness seine Agentendefinition weglässt.
Agent(subagent_type: "open-pr:pr-watcher", run_in_background: true,
name: "pr-watch-<number>",
prompt: "pr: <number>\nurl: <url>\nrepo: <owner/name>\nhead: <sha>\n"
"branch: <branch>\nlane: <gt|jj|git>\ncache: <dir>\nownership: <mine|foreign>\n"
"poll: bash \"<abs plugin root>/scripts/pr-poll.sh\" <owner/name> <number> <cache>/pr/<number>.json\n"
"Führe PR_POLL_WINDOW=40 <poll: command> allein als Vordergrund-Bash mit Timeout: 60000 aus, führe es sofort erneut aus bei DONE window-elapsed, und rufe es weiter auf, bis ein endgültiges Urteil vorliegt: Bewaffne niemals einen Monitor oder führe den Aufruf im Hintergrund aus, da keines einen Unteragenten aufweckt, wickle es niemals in eine Schleife ein und ersetze niemals eine handgemachte gh pr checks/bk-Schleife, die kein Warteschlangen-Landing sehen kann. Bei DONE ready-to-merge, sende SendMessage main vor allem anderen.")
Überprüfe nach dem Erzeugen, dass das Poll-Skript seine Zustandsdatei geschrieben hat:
bash "${CLAUDE_PLUGIN_ROOT}/scripts/pr-watch-armed.sh" "<cache>/pr/<number>.json"
Bei Exit-Code 1, sende dem Watcher dieselbe poll:-Zeile erneut über SendMessage und führe die Prüfung ein zweites Mal durch. Wenn es erneut fehlschlägt, melde dem User, dass die Überwachung unbewaffnet ist. Eine Agent-Erzeugung allein beweist nicht, dass das Skript läuft.
Ein Watcher pro PR – ein zweiter auf demselben PR würde den ersten überschreiben. Jeder Bericht außer evicted beendet die Überwachung; SendMessage mit Namen setzt sie für die nächste Runde fort. Eine evicted: <grund> <detail>-Nachricht kommt während des Laufs an, und der Watcher beobachtet weiter, bis der Aufrufer das erneute Einreihen per Label oder in der Graphite-Oberfläche vornimmt. Pushe jede Korrektur vor dem erneuten Einreihen; der Aufrufer entscheidet, wann er wieder einreiht.
Nach einem Ready-to-Merge-Bericht: open-pr.on-ready
Ein ready-to-merge-Bericht bedeutet, dass der PR grün, mergebar und genehmigt ist: Jede Prüfung bestanden, jede GitHub Actions-Prüfungs-Suite auf dem Head abgeschlossen, mergeable ist true, der Warteschlangenstatus wurde sauber gelesen (niemals QUEUE unknown), und der PR ist weder eingereiht noch entfernt auf seinem aktuellen Head. Keine aktuelle Überprüfung eines Reviewers ist CHANGES_REQUESTED, und der REST mergeable_state ist nicht blocked (der Zustand für eine fehlende erforderliche Genehmigung). Ein ready-to-merge downstack #<n>-Bericht ist ein gestapelter PR, der auf den Downstack-PR # wartet (auch wenn Graphites Mergeability-Prüfung die einzige unvollendete Prüfung in einem veralteten Graphite-Stapel ist). Der PR selbst ist bereit, landet aber nur mit seinem Downstack: Nenne # in der Frage und reihe den Stapel ein, niemals diesen PR allein.
Lies in der CLAUDE.md des Users nach einer dieser genauen Zeilen:
open-pr.on-ready: offer-open(die Voreinstellung, wenn keine Zeile gesetzt ist): Führe im selben Zug den User überAskUserQuestion, ob die PR-Seite geöffnet werden soll. Führegh pr view <number> --webnur bei einem Ja aus.open-pr.on-ready: offer-merge: Führe im selben Zug „merge # jetzt?“ überAskUserQuestionaus. Füge das Warteschlangen-Label des Repos nur bei einem Ja hinzu.
Label oder öffne niemals allein aufgrund des Berichts. Unter dem long-running-Skill leite den Bericht an den Lande-Schalter weiter; er besitzt die Entscheidung unabhängig von der Einstellung.
Nach dem Hinzufügen des Warteschlangen-Labels zu einem PR, dessen Watcher bereits ready-to-merge gemeldet hat, setze diesen Watcher mit Namen fort, damit er die Warteschlange durch grüne Prüfungen bis zu einer Landung oder einem Fehlschlag beobachtet:
SendMessage(to: "pr-watch-<number>", message: "Queue label <label> added. Resume the queue watch on the same state file.")
Sein Bericht kommt als Benachrichtigung während der Aufgabe – arbeite weiter, bis er eintrifft. Wenn er ein Urteil meldet
…
[truncated for translation]