open-pr
Otevře pull request pro práci na aktuální větvi — zjistí forge a základní větev z projektové konfigurace, nezapsané změny nechá zapsat a odeslat přes make-commit, sestaví název podle Conventional Comm
SKILL.mdskills/open-pr/SKILL.md
GitHubOpen PR
Cílem je pull request otevřený proti správné základní větvi, s názvem a tělem,
ze kterých je poznat, co se mění a co se tím zavírá. Git mechaniku skill sám
nepíše — commit a push deleguje na sagittaras:make-commit, zakládání větve na
sagittaras:create-branch. Závazným kontraktem jsou sdílené soubory pluginu;
při rozporu s tímhle postupem platí ony.
| Soubor | Kdy ho otevři |
|---|---|
${CLAUDE_PLUGIN_ROOT}/shared/workflow-config.md |
V kroku 1, když projektová konfigurace chybí nebo v ní nenajdeš sekci Forge či Větvení |
${CLAUDE_PLUGIN_ROOT}/shared/git-scripts.md |
V kroku 1 před prvním voláním skriptu — pro argumenty a návratové kódy forge-detect.sh a gh/*.sh |
${CLAUDE_PLUGIN_ROOT}/shared/forge-recipes.md |
V kroku 6, dřív než sáhneš na tracker — včetně sekce s nástrahami |
Obsah sdílených souborů si přečti, ale nepřepisuj do odpovědi. Recepty se mění na jednom místě; kopie v konverzaci zastará a další běh podle ní založí PR jinak.
Vstupní kontext
- Zadání od volajícího (může být prázdné): $ARGUMENTS
Ze zadání vytěž, co v něm je: základní větev, číslo issue, které PR uzavírá, milestone, do kterého PR patří, a výslovný souhlas k mergi (fráze jako „a mergni", „udělej i merge", „vytvoř PR a slej to", „a rovnou zmerguj"). Co v zadání není, doplň postupem níže — ale nikdy nepřebíjej to, co volající předal.
Souhlas k mergi musí být explicitní a musí pocházet z promptu, kterým byl
aktuální běh spuštěn — dispečuje-li tě run-milestone nebo implement-issue,
souhlas hledej v zadání, které ti předaly ony (musí ho samy přenést z původního
promptu uživatele, jinak ho nemáš odkud vzít). Domněnka z kontextu konverzace
nestačí: „otevři PR" bez dalšího slova souhlas k mergi neznamená.
Skill běží často neinteraktivně, spuštěný na konci jiné úlohy. Celý postup je proto napsaný tak, že se uživatele neptá — jediné místo, kde k němu míří otázka, je Eskalace v kroku 10.
Postup
1. Načti konfiguraci a zjisti stav
Přečti sekci ## Workflow (sagittaras) v CONTRIBUTING.md v kořeni cílového
projektu. Potřebuješ podsekci Forge (kterou větev receptů použít a jaké
owner/repo předat) a Větvení (výchozí větev, tvar integrační větve,
a že do výchozí větve mergeuje jen člověk).
CONTRIBUTING.mdneexistuje nebo sekci nemá → nepokračuj a nedomýšlej si hodnoty. Řekni to a nabídni/sagittaras:init-workflow.- Chybí podsekce, kterou potřebuješ → řekni která a nabídni doplnění; sám ji za pochodu nedoplňuj.
Pak zjisti stav repozitáře:
bash "${CLAUDE_PLUGIN_ROOT}/scripts/forge-detect.sh"
Reaguj podle návratového kódu:
- 2
not_a_git_repository→ ohlas a skonči. - 3 chybějící remote nebo neodvoditelné
owner/repo→ ohlas a skonči. PR je operace nad remotem; lokální repozitář bez něj nemá kam PR založit. forge=unknown→ typ forge ber ze sekceForgekonfigurace, ta je pro výběr receptů stejně autoritativní. Chybí-li ale iowner/repo, zastav se — volání by nemělo kam mířit.
Liší-li se owner/repo z detekce od konfigurace, nehádej, který je správný
a ohlas rozpor: obvykle to znamená, že běžíš nad jiným repozitářem, než pro
který konfigurace platí, a PR by vzniklo jinde.
Nakonec si přečti stav pracovní kopie:
git branch --show-current
git status -sb --porcelain
Z git status -sb vyčteš zároveň upstream a předstih větve ([ahead N]) —
obojí potřebuješ v krocích 4 a 5 a bez upstreamu nemá origin co porovnávat.
Přímé volání git je tu v pořádku právě proto, že nic nemění — všechno, co
do repozitáře zapisuje, jde přes delegované skilly.
2. Urči větev, ze které PR poroste
Volající obvykle už na své větvi stojí. Pak ji použij a novou nezakládej — její commity by na nové větvi nebyly a PR by vzniklo prázdné.
- Jsi na jiné než výchozí větvi → to je head PR, jdi dál.
- Jsi na výchozí větvi a máš nezapsané změny → není na čem stavět, sáhni
po
sagittaras:create-branch(změny přeberou s sebou) a pokračuj na nově založené větvi. Předej mu hotový název ve tvaru<type>/<popis>odvozený z rozpracovaných změn — bez něj si ho nechá potvrdit uživatelem a v autonomním běhu se zastaví. Skončí-licreate-branchscheckout_failed, větev nevznikla a zůstáváš na výchozí; ohlas to a nepokračuj. - Jsi na výchozí větvi a všechno je zapsané → zastav se a ohlas to. Přesunout hotové commity z výchozí větve jinam je zásah do historie, který tenhle skill záměrně neumí.
- Odpojená HEAD → zastav se a ohlas to. Commit i větev by se ztratily při prvním přepnutí.
3. Urči základní větev
Základ PR je větev, ze které se práce vyvíjela:
- Předal-li ji volající (typicky integrační větev
milestone/<slug>v milestone běhu), platí jeho hodnota. Výchozí větev z konfigurace si v tom případě nedomýšlej — PR mířící mimo integrační větev obejde integrační bránurun-milestonea zamíří rovnou do výchozí větve. - Jinak vezmi výchozí větev ze sekce
Větvení.
Že má head větev proti základní vůbec nějaký commit, ověřuj až po kroku 4 — volající typicky předává práci ještě nezapsanou a v tuhle chvíli by kontrola zastavila i běh, který je úplně v pořádku.
4. Zapiš a odešli rozdělanou práci
Je-li pracovní strom čistý a větev už pushnutá (upstream i nulový předstih
z kroku 1), krok přeskoč. Jinak zavolej nástrojem Skill skill
sagittaras:make-commit. Vlastní commit logiku nepiš — rozdělení do celků,
formát zprávy i push jsou jeho práce a psát je podruhé znamená dvě různá
pravidla pro tutéž věc.
Publikaci větve si vyžadovat nemusíš — make-commit pushuje po každém commitu
a větev bez upstreamu sám publikuje. Push mu proto nezakazuj: nad nepushnutou
větví PR založit nejde.
Skončí-li make-commit přesto s nepublikovanou větví, zastav se a eskaluj.
Nedopushovávej ji sám: publikace je jeho výchozí chování, takže její absence
znamená překážku, kterou ohlásil (chybí remote, remote push odmítl) — a obejít
ji vlastním pushem znamená publikovat větev, o které nevíš, proč publikovaná
není.
Ohlásí-li make-commit, že necommitnul (zastavil se na brzdě, odmítl commit
hook), zastav se a ohlas příčinu. Commit kolem něj neobcházej.
Teď ověř, že head větev má proti základní aspoň jeden commit navíc:
git fetch origin <base> && git rev-list --count "origin/<base>..HEAD"
Porovnávej proti remote refu, ne proti lokální větvi: základní větev
v milestone běhu často lokálně vůbec není a zastaralý ref vydá věrohodně
vypadající špatné číslo. Vyjde-li 0, nezakládej nic a ohlas to — prázdné PR
obě forge založí, ale nemá co recenzovat.
5. Sestav název a tělo
Název je Conventional Commit odpovídající odvedené práci, ve stejném tvaru
jako názvy issues: <type>(<scope>): <popis>. Uzavírá-li PR právě jedno issue,
vezmi jeho název doslova — tracker pak ukazuje tentýž řetězec dvakrát a nic
se nerozchází. Jinak ho odvoď ze zapsaných commitů, ne ze zadání.
Tělo piš podle Formátu výstupu: krátké shrnutí a Closes #N, jen když PR
opravdu nějaké issue uzavírá.
Na GitHubu ho zapiš do dočasného souboru mimo pracovní strom repozitáře —
soubor uvnitř stromu by skončil jako nesledovaná veteš v příštím commitu. Zapisuj
heredocem s ukončovačem v uvozovkách ve stejném volání, ve kterém soubor vznikne,
jinak shell expanduje $ a zpětné apostrofy a do PR dorazí něco jiného, než jsi
napsal:
f="$(mktemp)"; cat >"$f" <<'BODY'
<tělo>
BODY
echo "body_file=$f"
Po založení PR soubor smaž. Na Gitea tenhle mezikrok odpadá — tělo se předává přímo parametrem volání a žádný shell v cestě není.
Closes #Nzabírá na obou forge až při merge do výchozí větve. V milestone běhu, kde PR míří do integrační větve, se tím issue nezavře; odkaz tam má smysl jako vazba, zavření vlastnírun-milestoneaclose-milestone.
6. Založ PR
Otevři ${CLAUDE_PLUGIN_ROOT}/shared/forge-recipes.md, vyber sloupec podle
sekce Forge z konfigurace a volání neodvozuj z hlavy. Na Gitea si nejdřív
jedním voláním ToolSearch načti odložené nástroje podle řádku „Pracuje
s PR".
Každý gh skript potřebuje -R <owner/repo> ze sekce Forge konfigurace.
Bez něj skončí kódem 2 — a řídit se aktuálním adresářem nemůže, protože
v izolovaném worktree run-milestone nemusí ukazovat na správný repozitář.
Než PR založíš, vypiš otevřená PR a podívej se, jestli už z téhle head větve
jedno neexistuje — na GitHubu bash "${CLAUDE_PLUGIN_ROOT}/scripts/gh/pr-list.sh" -R <owner/repo> --state open a porovnání pole headRefName ve vráceném JSON, na
Gitea list_pull_requests se state: "open" a totéž porovnání. Recepty řádek
„najdi PR podle head větve" nemají, tak je tady doslova.
Existuje-li takové PR, nezakládej druhé — vrať to stávající a skonči
úspěchem. Opakované spuštění po přerušeném běhu je normální stav, duplicitní PR
nad jednou větví ne. Liší-li se ale u stávajícího PR baseRefName od základní
větve z kroku 3, jde o rozpor, který sám nerozsoudíš: eskaluj.
bash "${CLAUDE_PLUGIN_ROOT}/scripts/gh/pr-create.sh" -R <owner/repo> \
--base <base> --head <head> --title <název> --body-file <cesta k tělu>
Tělo předávej gh skriptům vždy souborem (--body-file), nikdy argumentem:
víceřádkový markdown se v shellu o uvozovky a zpětné apostrofy rozbije, a rozbije
se tiše. Na Gitea shell v cestě není — tam předej pull_request_write obsah
těla přímo v parametru body a dočasný soubor nezakládej vůbec.
Skript vrátí number= a url=. Kód 2 je chybné volání, ne odmítnutí forge:
oprav argumenty (typicky chybějící -R) a teprve pak opakuj — opakování beze
změny selže znovu. Kód 7 znamená chybějící gh nebo přihlášení; řekni to
rovnou, ne až po dalších krocích. U chyby 404 na zápisu ověř oprávnění účtu
podle nástrah v receptech; jiný repozitář nezkoušej.
7. Přiřaď milestone
Patří-li PR do milestonu, přiřaď mu ho druhým voláním hned po založení.
Tvar argumentů vezmi z řádku „Přiřaď PR milestone" v receptech — identifikátor
se mezi forge liší (gh skript bere název milestonu, Gitea update číselné
id) a záměna je jedna z tamních nástrah. gh větev nezapomene -R <owner/repo>.
Při zakládání to nejde ani na jedné forge a není to kosmetika: close-milestone
podle téhle vazby integrační PR dohledává.
Selže-li přiřazení, PR nerušit — už existuje a je platné. Ohlas jeho číslo
spolu s tím, že milestone přiřazený není, ať to jde doplnit jedním voláním;
mlčky přejít se to nedá, close-milestone by pak milestone nezavřel.
Nepatří-li PR do milestonu, krok přeskoč.
8. Proveď merge, obsahoval-li prompt výslovný souhlas
Nenašel-li krok „Vstupní kontext" v promptu, kterým byl aktuální běh spuštěn, výslovný souhlas k mergi, krok přeskoč — PR zůstává otevřené, to je současné chování beze změny.
Souhlas našel → mergni podle řádku „Mergni PR" v receptech, strategií ze
sekce Větvení (squash) a se smazáním zdrojové větve:
bash "${CLAUDE_PLUGIN_ROOT}/scripts/gh/pr-merge.sh" <n> --squash --delete-branch
Mergovat smíš do jakékoli základní větve — souhlas v promptu je přesně ta
výjimka, kterou řádek merge do výchozí větve: jen člověk v sekci Větvení
připouští; bez tohohle kroku by řádek platil bez výjimky. Neplyne z toho nic
o integrační bránu run-milestone — ta svůj vlastní merge do integrační větve
provádí sama (jeho vlastní krok 8), tenhle krok se týká jen PR, které
zakládáš ty.
result=conflict nebo jiné nenulové selhání merge neobcházej — PR zůstává
otevřené a nemergnuté, ohlas to v souhrnu a eskaluj podle kroku 10. Nezkoušej
force merge ani jiný recept.
9. Shrň výsledek
Vypiš souhrn podle Formátu výstupu: číslo a odkaz PR, base a head větev, co uzavírá, přiřazený milestone, výsledek merge (proveden, nebo „neprovádí se") a co jsi cestou přeskočil nebo delegoval. Merge nenabízej jako svůj další krok — bez souhlasu v promptu se tady skill zastavuje.
10. Eskalace
Přeruš postup a ohlas stav, nastane-li kterákoli z těchto situací:
- chybí projektová konfigurace nebo v ní chybí sekce
ForgečiVětvení; forge-detect.shskončí kódem2nebo3, nebo neznáowner/repo;owner/repoz detekce se liší od konfigurace;- stojíš na výchozí větvi se vším zapsaným, nebo na odpojené HEAD;
create-branchvětev nezaložil (checkout_failed);make-commitnecommitnul, nebo větev zůstala nepublikovaná;- head větev nemá ani po kroku 4 proti základní žádný commit navíc;
- z téhle head větve už existuje otevřené PR proti jiné základní větvi (shodné PR není důvod k eskalaci — vrať ho a skonči);
- PR vzniklo, ale přiřazení milestonu selhalo;
- prompt obsahoval souhlas k mergi, ale merge v kroku 8 selhal (konflikt, odmítnutí forge);
- forge vrátí 404 nebo
ghchybí či není přihlášené.
Eskalace vždy shrne, co už vzniklo (commit, větev, PR), a položí jednu konkrétní otázku nástrojem AskUserQuestion. Selže-li volání nebo odpověď nedorazí, je uživatel mimo hru: nezakládej nic dalšího a stav jen ohlas — nezaložený PR se doplní jedním během, kdežto zbloudilý PR proti výchozí větvi uklízí někdo ručně.
Formát výstupu
Tělo PR (krok 5) — Closes řádek vynech, když PR žádné issue neuzavírá:
<jedna až tři věty: co PR mění a proč, bez výčtu souborů>
Closes #<n>
Souhrn (krok 9) — řádek Merge má dvě platné podoby:
PR #<číslo>: <název> — <url>
| | |
| --- | --- |
| Base | <základní větev> |
| Head | <pracovní větev> |
| Uzavírá | #<n>, nebo „—" |
| Milestone | <název>, nebo „—" |
Commity: <počet, nebo „nic nového k zapsání">
Merge: neprovádí se
Obsahoval-li prompt souhlas a merge v kroku 8 prošel, poslední řádek nahraď:
Merge: proveden — squash do <základní větev>, zdrojová větev smazána
Zásady
- Skill mergne jen na výslovný souhlas v promptu, jinak nikdy. Merge do
integrační větve vlastní
run-milestonesám; do výchozí větve mergneopen-prvýhradně tehdy, když prompt, kterým byl aktuální běh spuštěn, obsahoval výslovný souhlas k mergi (krok 8). Bez něj je výstupem jen otevřené PR, stejně jako dosud. - Základní větev se nedomýšlí. Co předal volající, platí; výchozí větev z konfigurace je až fallback.
- Git mechanika se deleguje bez výjimky. Commit, push i publikace větve přes
sagittaras:make-commit, větev přessagittaras:create-branch. Napsat je potřetí znamená tři různá chování téže operace. - Jedna head větev, jedno PR. Před zakládáním se ověřuje, že už neexistuje.
- Tělo
ghskriptům vždy souborem, nikdy argumentem. Na Gitea, kde shell v cestě není, se předává obsah přímo. - Repozitář se
ghskriptům předává-R owner/repo. Aktuální adresář v izolovaném worktree nemusí být ten repozitář, o který jde. - Sdílený kontrakt má přednost. Odporuje-li tenhle postup receptům, konfiguraci nebo kontraktu skriptů, platí ony.