Auto-Updater Skill
一个面向 Other 场景的 Agent 技能。原始说明:Automatically update Clawdbot and all installed skills once daily. Runs via cron, checks for updates, applies them, and messages the user with a summary of what changed.
name: fork-manager
description: Manage forks with open PRs - sync upstream, rebase branches, track PR status, and maintain production branches with pending contributions. Supports automatic conflict resolution via --auto-resolve flag (spawns AI subagents to resolve rebase conflicts). Use when syncing forks, rebasing PR branches, building production branches that combine all open PRs, reviewing closed/rejected PRs, or managing local patches kept outside upstream. Requires Git and GitHub CLI (gh).
metadata: {"openclaw": {"requires": {"bins": ["git", "gh"]}}}
Manage forks where you contribute PRs but also use improvements before they're merged upstream. Includes support for local patches — fixes kept in the production branch even when the upstream PR was closed/rejected.
github skill insteadissue-prioritizer skill insteadpr-review skill insteadgh pr create directlyA skill NUNCA deve ser executada inline pelo agente principal. Sempre usar o padrão orchestrator/worker:
sessions_spawn(
task: "<prompt completo com contexto do repo, config, último history>",
model: "<model adequado>",
mode: "run"
)
sessions_list / sessions_history:subagents kill + spawna novo workergit status, último checkpoint)O orchestrator deve incluir no prompt do worker:
When invoked by a cron job (automated recurring sync), follow these guidelines for efficient execution:
🍴 Fork Sync Complete — <repo>
Main: synced N commits (old_sha → new_sha)
PRs: X open, Y changed state
- Rebased: A/B clean (C conflicts)
Production: rebuilt clean | N conflicts
Notable upstream: [1-3 bullet highlights]
repos/<name>/checkpoint.json so the next run (or manual invocation) can resumeConfigs are organized per repository in repos/<repo-name>/config.json relative to the skill directory:
fork-manager/
├── SKILL.md
├── scripts/
│ └── update-config.mjs
└── repos/
├── project-a/
│ └── config.json
└── project-b/
└── config.json
Formato do config.json:
{
"repo": "owner/repo",
"fork": "your-user/repo",
"localPath": "/path/to/local/clone",
"mainBranch": "main",
"productionBranch": "main-with-all-prs",
"upstreamRemote": "upstream",
"forkRemote": "origin",
"autoResolveConflicts": false,
"openPRs": [123, 456],
"prBranches": {
"123": "fix/issue-123",
"456": "feat/feature-456"
},
"localPatches": {
"local/my-custom-fix": {
"description": "Breve descrição do que o patch faz",
"originalPR": 789,
"closedReason": "rejected|superseded|duplicate|wontfix",
"keepReason": "Motivo pelo qual mantemos localmente",
"addedAt": "2026-02-07T00:00:00Z",
"reviewDate": "2026-03-07T00:00:00Z"
}
},
"lastSync": "2026-01-28T12:00:00Z",
"notes": {
"mergedUpstream": {},
"closedWithoutMerge": {},
"droppedPatches": {}
}
}
openPRs and prBranches are a local cache, not the source of truth.
The source of truth for open PRs is GitHub.
Before any command that depends on the PR set (status, rebase-all,build-production, full-sync, audit-open), run:
node <skillDir>/scripts/update-config.mjs --config <skillDir>/repos/<repo-name>/config.json
Use --check to verify without writing and --dry-run to print the updated
JSON. Do not build production from a stale openPRs list. A config that is
missing an open PR by the configured fork owner is incomplete and must be
updated before rebasing or rebuilding production.
autoResolveConflicts)A resolução automática pode ser ativada de duas formas (qualquer uma basta):
/fork-manager --auto-resolve
/fork-manager full-sync --auto-resolve
{ "autoResolveConflicts": true }
| Fonte | Comportamento |
|-------|---------------|
| Nenhuma (default) | Conflitos são reportados mas não resolvidos. Relatório inclui "⚠️ Conflitos requerem aval do desenvolvedor." |
| --auto-resolve OU config.autoResolveConflicts: true | Spawna subagentes Opus para resolver conflitos. Resultados classificados como trivial/semântico/irresolvível. |
Precedência: --auto-resolve na invocação ativa a resolução mesmo se o config diz false. Não existe --no-auto-resolve — se o config diz true e o usuário não quer resolver, basta não rodar o passo manualmente.
Para usuários do ClawHub: basta passar --auto-resolve no comando. Nenhuma configuração de repo necessária.
localPatchesCada entry em localPatches é uma branch local mantida na production branch mas sem PR aberto no upstream.
| Campo | Descrição |
|-------|-----------|
| description | O que o patch faz |
| originalPR | Número do PR original que foi fechado (opcional se criado direto como patch) |
| closedReason | Por que o PR foi fechado: rejected (mantenedor recusou), superseded (outro PR resolve parcialmente mas não totalmente), duplicate (fechamos nós mesmos), wontfix (upstream não vai resolver) |
| keepReason | Por que precisamos manter localmente |
| addedAt | Data em que foi convertido para local patch |
| reviewDate | Data para reavaliar se ainda é necessário (upstream pode ter resolvido) |
Cada repositório gerenciado tem um arquivo history.md que registra todas as execuções da skill como um livro de registro append-only:
fork-manager/
└── repos/
├── project-a/
│ ├── config.json
│ └── history.md
└── project-b/
├── config.json
└── history.md
Antes de qualquer operação, ler o history.md do repositório alvo e extrair a última entrada (último bloco ---). Isso dá contexto sobre:
# Ler última entrada do history (tudo após o último "---")
tail -n +$(grep -n '^---$' "$SKILL_DIR/repos/<repo-name>/history.md" | tail -1 | cut -d: -f1) "$SKILL_DIR/repos/<repo-name>/history.md"
Se o arquivo não existir, criar com o header e prosseguir normalmente.
Ao final de toda execução, fazer append ao history.md com o resultado completo. Formato:
---
## YYYY-MM-DD HH:MM UTC | <comando>
**Operator:** <claude-code | openclaw-agent | manual>
### Summary
- Main: <status do sync>
- PRs: <X open, Y merged, Z closed, W reopened>
- Local Patches: <N total, M com review vencida>
- Production: <rebuilt OK | not rebuilt | build failed>
### Actions Taken
- <lista de ações executadas, ex: "Synced main (was 12 commits behind)">
- <"Rebased 21/21 branches clean">
- <"PR #999 closed → kept as local patch local/my-fix">
- <"PR #777 reopened → restored to openPRs (was in droppedPatches)">
### Pending
- <ações que ficaram pendentes, ex: "PR #456 has conflicts — needs manual resolution">
- <"3 local patches with expired reviewDate — run review-patches">
### Full Report
<o relatório completo que seria mostrado ao usuário, colado aqui na íntegra>
Importante: O bloco Full Report contém o relatório completo sem abreviação. Isso garante que o próximo agente que ler o history tenha toda a informação, não apenas o resumo.
Resolve the skill directory (where SKILL.md lives):
# SKILL_DIR is the directory containing this SKILL.md
# Resolve it relative to the agent's workspace or skill install path
SKILL_DIR="<path-to-fork-manager-skill>"
# Load config for the target repo
cat "$SKILL_DIR/repos/<repo-name>/config.json"
# Ler último output do history para contexto
HISTORY="$SKILL_DIR/repos/<repo-name>/history.md"
if [ -f "$HISTORY" ]; then
# Extrair última entrada (após último ---)
LAST_SEP=$(grep -n '^---$' "$HISTORY" | tail -1 | cut -d: -f1)
if [ -n "$LAST_SEP" ]; then
tail -n +"$LAST_SEP" "$HISTORY"
fi
fi
cd <localPath>
git fetch <upstreamRemote>
git fetch <originRemote>
# Commits que upstream tem e origin/main não tem
git log --oneline <originRemote>/<mainBranch>..<upstreamRemote>/<mainBranch>
# Contar commits atrás
git rev-list --count <originRemote>/<mainBranch>..<upstreamRemote>/<mainBranch>
# Listar PRs abertos do usuário
gh pr list --state open --author @me --json number,title,headRefName,state
# Verificar status de um PR específico
gh pr view <number> --json state,mergedAt,closedAt,title
Para cada PR no config, verificar:
| Estado | Condição | Ação |
| ------------ | --------------------------------- | --------------------------------------- |
| open | PR aberto no GitHub | Manter, verificar se precisa rebase |
| merged | PR foi mergeado | Remover do config, deletar branch local |
| closed | PR fechado sem merge | Acionar review-closed (ver abaixo) |
| conflict | Branch tem conflitos com upstream | Precisa rebase manual |
| outdated | Branch está atrás do upstream | Precisa rebase |
Comando para verificar se branch precisa rebase:
git log --oneline <upstreamRemote>/<mainBranch>..<originRemote>/<branch> | wc -l # commits à frente
git log --oneline <originRemote>/<branch>..<upstreamRemote>/<mainBranch> | wc -l # commits atrás
review-closed)Quando um PR é detectado como fechado sem merge, NÃO remover automaticamente. Iniciar um fluxo de revisão interativo:
# Buscar comentários e motivo do fechamento
gh pr view <number> --repo <repo> --json title,closedAt,state,comments,labels
# Verificar se upstream resolveu o problema de outra forma
# (procurar PRs mergeados recentes que toquem os mesmos arquivos)
gh pr list --state merged --repo <repo> --json number,title,mergedAt --limit 30
| Categoria | Descrição | Ação padrão |
|-----------|-----------|-------------|
| resolved_upstream | Upstream corrigiu o problema por outro caminho | drop — não precisamos mais |
| supersededbyours | Fechamos nós mesmos em favor de outro PR nosso | drop — o substituto já está em openPRs |
| rejected_approach | Mantenedor não gostou da abordagem, mas o bug/feature existe | review — considerar resubmeter com abordagem diferente |
| rejected_need | Mantenedor não concorda que é um problema | review — avaliar se precisamos localmente |
| wontfix | Upstream marcou como wontfix | review — provável candidato a local patch |
Para cada PR fechado, apresentar:
### PR #<number> — <title>
- **Fechado em:** <data>
- **Motivo:** <categoria>
- **Comentários do mantenedor:** <resumo>
- **O fix ainda é relevante pra nós?** Análise: <o que o patch faz e se upstream resolve>
**Opções:**
1. 🗑️ **Drop** — remover completamente (branch local + remote)
2. 📌 **Keep as local patch** — mover para `localPatches`, manter na production branch
3. 🔄 **Resubmit** — retrabalhar e abrir novo PR com abordagem diferente
4. ⏸️ **Defer** — manter no limbo por agora, revisitar depois
Drop:
git branch -D <branch> 2>/dev/null
git push <originRemote> --delete <branch> 2>/dev/null
# Mover para notes.droppedPatches no config
Keep as local patch:
# Branch continua existindo, mas sai de openPRs/prBranches
# Entra em localPatches com metadata completa
# Renomear branch de fix/xxx para local/xxx (opcional, para clareza)
Resubmit:
# Manter branch, criar novo PR com descrição atualizada
gh pr create --title "<novo titulo>" --body "<nova descrição com contexto>"
# Atualizar config com novo número de PR
Defer:
# Mover para uma seção notes.deferred no config
# Será apresentado novamente no próximo full-sync
audit-open)Análise proativa dos PRs ainda abertos para detectar redundâncias e obsolescência. Deve rodar no full-sync depois do update-config.
Verificar se o upstream já resolveu o problema que nosso PR corrige, sem mergear nosso PR:
# Para cada PR aberto, buscar os arquivos que ele toca
gh pr view <number> --repo <repo> --json files --jq '[.files[].path]'
# Verificar se upstream alterou esses mesmos arquivos recentemente
# (commits no upstream/main que não estão no nosso PR branch)
git log --oneline upstream/main --since="<lastSync>" -- <files>
# Se houve mudanças upstream nos mesmos arquivos, verificar se o diff
# do nosso PR ainda faz diferença (pode ter sido absorvido)
git diff upstream/main..origin/<branch> -- <files>
Se o diff do PR estiver vazio (upstream absorveu as mudanças): marcar como resolved_upstream.
Se o diff for parcial (upstream resolveu parte): marcar como partially_resolved para revisão.
Verificar se outra pessoa abriu um PR que resolve o mesmo problema:
# Buscar PRs abertos no upstream que tocam os mesmos arquivos
gh pr list --state open --repo <repo> --json number,title,headRefName,files --limit 50
# Buscar PRs mergeados recentes que tocam os mesmos arquivos
gh pr list --state merged --repo <repo> --json number,title,mergedAt,files --limit 30 \
| jq '[.[] | select(.mergedAt >= "<lastSync>")]'
Para cada PR encontrado que toca os mesmos arquivos, comparar:
Se houver match forte: marcar como duplicate_external ou superseded_external.
Detectar sobreposição entre nossos próprios PRs abertos:
# Coletar files de todos os nossos PRs abertos
for pr in <openPRs>; do
gh pr view $pr --repo <repo> --json number,files --jq '{number, files: [.files[].path]}'
done
# Cruzar: se dois PRs tocam os mesmos arquivos, são candidatos a duplicata
Para cada par com overlap de arquivos:
### Audit de PRs Abertos
#### Possivelmente resolvidos upstream
| # | Titulo | Arquivos em comum | Status |
|---|--------|-------------------|--------|
| 123 | fix(foo): bar | foo.ts (changed upstream 3 days ago) | ⚠️ Verificar |
#### Possíveis duplicatas externas
| Nosso PR | PR externo | Overlap | Recomendação |
|----------|-----------|---------|--------------|
| #123 | #456 (@user) | foo.ts, bar.ts | ⚠️ Mesmo issue, verificar |
#### Self-duplicates (nossos PRs que se sobrepõem)
| PR A | PR B | Arquivos em comum | Recomendação |
|------|------|-------------------|--------------|
| #6471 | #8386 | skills/refresh.ts | 🗑️ Fechar #6471 (duplicata) |
**Opções por PR flagged:**
1. 🗑️ **Close** — fechar o PR no upstream e drop
2. ✅ **Keep** — falso positivo, manter aberto
3. 🔄 **Merge into** — combinar com outro PR
4. ⏸️ **Defer** — revisitar depois
status - Verificar estado atualsync - Sincronizar main com upstreamcd <localPath>
git fetch <upstreamRemote>
git checkout <mainBranch>
git merge <upstreamRemote>/<mainBranch>
git push <originRemote> <mainBranch>
rebase <branch> - Rebase de uma branch específicagit checkout <branch>
git fetch <upstreamRemote>
git rebase <upstreamRemote>/<mainBranch>
# Se conflito: resolver e git rebase --continue
git push <originRemote> <branch> --force-with-lease
rebase-all - Rebase de todas as branches de PRPara cada branch em prBranches:
resolve-conflicts - Resolução automática de conflitos via subagentesRequer
--auto-resolvena invocação OUautoResolveConflicts: trueno config do repo. Se nenhum dos dois, este comando não é executado e conflitos são apenas reportados com a nota "⚠️ Conflitos requerem aval do desenvolvedor."
Após rebase-all detectar conflitos, o orchestrator (agente principal) spawna subagentes individuais para tentar resolver cada conflito automaticamente.
rebase-all retorna a lista de branches com conflitoCada subagente recebe:
Resolve o conflito de rebase da branch <branch> (PR #<number>) no repo <localPath>.
## Contexto
- Upstream: <upstreamRemote>/<mainBranch>
- Branch do PR: <originRemote>/<branch>
- Arquivos em conflito: <lista de arquivos do erro de rebase>
## Passos
1. cd <localPath>
2. git checkout -B <branch> <originRemote>/<branch> --no-track
3. git rebase <upstreamRemote>/<mainBranch>
→ O rebase vai parar com conflito
4. Para cada arquivo em conflito:
a. Ler o arquivo com os marcadores de conflito (<<<<<<<, =======, >>>>>>>)
b. Entender o que o upstream mudou (OURS) vs o que o PR mudou (THEIRS)
c. Resolver preservando a intenção de ambos
d. git add <arquivo>
5. git rebase --continue
6. Se houver mais conflitos em commits subsequentes, repetir 4-5
7. git push <originRemote> <branch> --force-with-lease
## Regras de resolução
- **Arquivo deletado no upstream + modificado pelo PR:** aceitar a deleção do upstream (nosso PR targeted código que não existe mais). git rm <arquivo> && git rebase --continue
- **Import/formatting conflicts:** mesclar ambos, preservar imports de ambos os lados
- **Lógica alterada em ambos os lados:** preservar a mudança do upstream E encaixar o fix do PR. Se o fix do PR não faz mais sentido com o novo código upstream, reportar como UNRESOLVABLE.
- **NUNCA alterar a lógica do PR** — apenas adaptar ao novo contexto do upstream
## Output
Responda com EXATAMENTE um destes formatos:
RESOLVED|<branch>|trivial|<resumo de 1 linha>
RESOLVED|<branch>|semantic|<resumo de 1 linha>
UNRESOLVABLE|<branch>|<motivo de 1 linha>
| Resultado | Significado | Ação |
|-----------|-------------|------|
| RESOLVED\|trivial | Conflito mecânico resolvido (imports, formatting, deleted files) | ✅ Push feito, sem necessidade de revisão |
| RESOLVED\|semantic | Conflito envolvendo lógica de negócio resolvido | ⚠️ Push feito, marcar no report para revisão humana |
| UNRESOLVABLE | Subagente não conseguiu resolver sem risco | ❌ Não faz push, escala no report |
Para branches resolvidas com sucesso:
git log --oneline <originRemote>/<branch> -1)notes.conflictBranches no config: remover entries resolvidasPara branches não resolvidas:
notes.conflictBranches com ciclo incrementadoApós resolve-conflicts, o build-production roda normalmente. Branches que foram resolvidas no rebase agora devem mergear clean na production. Se ainda houver conflito de production merge (diferente do conflito de rebase), o build-production trata como sempre: abort e reportar.
update-config - Atualizar config com PRs atuaisnode <skillDir>/scripts/update-config.mjs --config <skillDir>/repos/<repo-name>/config.json
The script queries GitHub with gh pr list --state open --author <fork owner>
(or --author @me when no fork is configured), treats GitHub as canonical for
open PRs, and rewrites openPRs + prBranches as a cache of the current open
set.
It also:
notes.closedWithoutMerge / notes.droppedPatchesopenPRsopenPRsnotes.mergedUpstreamnotes.closedWithoutMerge with reviewStatus: "pending"Useful modes:
node <skillDir>/scripts/update-config.mjs --config <config.json> --check
node <skillDir>/scripts/update-config.mjs --config <config.json> --dry-run
Ao comparar a lista do GitHub (gh pr list --state open) com o config local, detectar três cenários:
| Cenário | Condição | Ação |
|---------|----------|------|
| PR novo | No GitHub mas não em openPRs, localPatches, nem notes | Adicionar a openPRs + prBranches normalmente |
| PR reaberto (dropped) | No GitHub como open, encontrado em notes.closedWithoutMerge ou notes.droppedPatches | Restaurar: mover de volta para openPRs + prBranches, remover da seção notes. Fetch da branch: git fetch <originRemote> <branch>. Logar no relatório como "🔄 Reopened" |
| PR reaberto (local patch) | No GitHub como open, encontrado em localPatches (via campo originalPR) | Promover: mover de localPatches para openPRs + prBranches. Logar no relatório como "🔄 Reopened (was local patch)" |
Implementação:
# Para cada PR open no GitHub que NÃO está em openPRs:
# 1. Checar se o número está em notes.closedWithoutMerge ou notes.droppedPatches
# → Se sim: PR foi reaberto. Restaurar automaticamente.
# 2. Checar se algum entry em localPatches tem originalPR == número
# → Se sim: PR foi reaberto. Promover de volta a openPRs.
# 3. Se não encontrado em lugar nenhum: PR genuinamente novo.
# Restaurar branch se foi deletada:
git fetch <originRemote> <branch> 2>/dev/null || git fetch <originRemote> pull/<number>/head:<branch>
Nota: A restauração é automática (sem interação) porque o mantenedor reabrir um PR é sinal claro de que ele deve voltar ao tracking. O relatório sempre lista os PRs restaurados para visibilidade.
build-production - Criar branch de produção com todos os PRs + local patchesBefore rebuilding, run update-config and report any difference between the
GitHub open-PR set and the cached config. Continue only after the config includes
all currently open PRs by the authenticated contributor.
cd <localPath>
git fetch <upstreamRemote>
git fetch <originRemote>
# ⚠️ SEMPRE preservar arquivos não-commitados antes de trocar de branch
if [ -n "$(git status --porcelain)" ]; then
git stash push --include-untracked -m "fork-manager: pre-build-production $(date -u +%Y%m%dT%H%M%S)"
STASHED=1
fi
# Deletar branch antiga se existir
git branch -D <productionBranch> 2>/dev/null || true
# Criar nova branch a partir do upstream
git checkout -b <productionBranch> <upstreamRemote>/<mainBranch>
# 1. Mergear cada PR branch (contribuições upstream pendentes)
for branch in <prBranches>; do
git merge <originRemote>/$branch -m "Merge PR #<number>: <title>"
# Se conflito, resolver
done
# 2. Mergear cada local patch (fixes mantidos localmente)
for branch in <localPatches>; do
git merge <originRemote>/$branch -m "Merge local patch: <description>"
# Se conflito, resolver
done
# Push
git push <originRemote> <productionBranch> --force-with-lease
# Restaurar arquivos não-commitados
if [ "$STASHED" = "1" ]; then
git stash pop
fi
After rebuilding the production branch, remind the user to run their project's build command if needed.
Ordem de merge: PRs abertos primeiro (ordem crescente por número), local patches depois. Isso garante que patches locais se aplicam sobre a base mais completa possível.
audit-open - Auditar PRs abertos por redundância/obsolescênciaAnálise proativa de todos os PRs abertos (seção 8 acima):
review-closed - Revisar PRs recém-fechadosDetecta PRs que foram fechados/mergeados desde o último sync e guia o usuário na decisão:
notes.mergedUpstream, deletar branchesreview-patches - Reavaliar patches locais existentesPara cada entry em localPatches cuja reviewDate já passou:
full-sync - Sincronização completagit stash --include-untracked se houver arquivos não-commitadossync - Atualizar mainOLD_SHA=$(git rev-parse upstream/main)NEW_SHA=$(git rev-parse upstream/main)post-sync hooks (optional, repo-specific) - Run custom post-sync actionsOLD_SHA == NEW_SHA (no upstream changes)config.json under "postSyncHooks" (array of shell commands or descriptions)update-config - Atualizar lista de PRs a partir do GitHub (obrigatório; openPRs é cache)review-closed - Revisar PRs recém-fechados/mergeados (interativo)audit-open - Auditar PRs abertos por redundância/obsolescência (interativo)review-patches - Reavaliar local patches com reviewDate vencida (interativo)rebase-all - Rebase de todas as branches (PRs + local patches)resolve-conflicts (only if --auto-resolve flag OR autoResolveConflicts: true in config) - Resolver conflitos de rebase automaticamente via subagentes (Opus, até 5 paralelos, 10min timeout cada). Se nenhum dos dois, pular este passo.build-production - Recriar branch de produção (PRs + local patches)git stash pop para restaurar arquivos locaisNota sobre ordem: update-config roda antes de review-closed porque é ali que PRs reabertos são detectados e restaurados automaticamente. Depois, review-closed processa PRs que foram genuinamente fechados. Por fim, audit-open roda por último, já com a lista de PRs abertos atualizada (incluindo os reabertos).
Após qualquer operação, gerar relatório:
## 🍴 Fork Status: <repo>
### Upstream Sync
- **Main branch:** X commits behind upstream
- **Last sync:** <date>
### Open PRs (Y total)
| # | Branch | Status | Action Needed |
| --- | ------------- | ---------------- | ----------------- |
| 123 | fix/issue-123 | ✅ Up to date | None |
| 456 | feat/feature | ⚠️ Needs rebase | Run rebase |
| 789 | fix/bug | ❌ Has conflicts | Manual resolution |
#### 🔧 Resolução Automática de Conflitos
_Seção presente apenas quando resolução automática está ativa (`--auto-resolve` ou `autoResolveConflicts: true`). Caso contrário, substituir por:_
> ⚠️ **Conflitos requerem aval do desenvolvedor.** Resolução automática não ativada. Use `--auto-resolve` para tentar resolver automaticamente.
_Quando ativa: Conflitos semânticos (⚠️) foram resolvidos automaticamente mas **requerem revisão humana** — o subagente pode ter interpretado mal a intenção do código._
| # | Branch | Tipo | Resultado | Detalhe |
| --- | ------------- | --------- | ------------------ | -------------------------------- |
| 123 | fix/issue-123 | trivial | ✅ Resolvido | Removed deleted test file |
| 456 | fix/issue-456 | semântico | ⚠️ Resolvido (revisar) | Adapted runner call to new API |
| 789 | fix/issue-789 | — | ❌ Não resolvido | Lógica incompatível com upstream |
#### 🔴 Conflitos persistentes (3+ ciclos)
_Seção presente apenas quando há conflitos que persistem por 3 ou mais execuções consecutivas da skill, mesmo após tentativa de resolução automática. Esses PRs merecem atenção prioritária: considerar dropar, recriar sobre o main atual, ou resolver manualmente._
| # | Branch | Ciclos | Arquivo(s) | Recomendação |
| --- | ------------- | ------ | ----------------- | ------------------- |
| 789 | fix/bug | 5 | agent-runner.ts | 🗑️ Dropar ou recriar |
### Local Patches (Z total)
| Branch | Original PR | Motivo | Review em |
| ------------------ | ----------- | --------------- | ---------- |
| local/my-fix | #321 | rejected_need | 2026-03-07 |
| local/custom-tweak | — | wontfix | 2026-04-01 |
### Audit de PRs Abertos
| # | Título | Flag | Detalhe |
| --- | ---------------- | ------------------- | -------------------------------- |
| 123 | fix(foo): bar | ⚠️ resolved_upstream | upstream changed foo.ts 3d ago |
| 456 | fix(baz): qux | ⚠️ duplicate_external | similar to #789 by @user |
| 111 | fix(a): b | ⚠️ self_duplicate | overlaps with our #222 |
### PRs Reabertos (restaurados automaticamente)
| # | Título | Origem | Ação |
| --- | ---------------- | ------------------- | ----------------------- |
| 777 | fix(foo): bar | notes.droppedPatches | 🔄 Restored to openPRs |
| 888 | feat(baz): qux | localPatches | 🔄 Promoted to openPRs |
_Seção presente apenas quando há PRs reabertos no ciclo atual._
### PRs Recém-Fechados (aguardando decisão)
| # | Título | Fechado em | Motivo | Recomendação |
| --- | ---------------- | ---------- | ------------------- | ---------------- |
| 999 | fix(foo): bar | 2026-02-05 | resolved_upstream | 🗑️ Drop |
| 888 | feat(baz): qux | 2026-02-06 | rejected_need | 📌 Local patch |
### Production Branch
- **Branch:** main-with-all-prs
- **Contains:** PRs #123, #456 + Local patches: local/my-fix, local/custom-tweak
- **Status:** ✅ Up to date / ⚠️ Needs rebuild
### Recommended Actions
1. ...
2. ...
--force-with-lease em vez de --force para push--auto-resolve ou autoResolveConflicts: true): Quando ativa, após rebase-all a skill spawna subagentes (Opus, até 5 paralelos, 10min timeout cada) para tentar resolver conflitos. Conflitos triviais (imports, formatting, arquivos deletados) são resolvidos e pushed sem necessidade de revisão. Conflitos semânticos (lógica de negócio) são resolvidos e pushed mas marcados no relatório como ⚠️ para revisão humana. Se o subagente não conseguir resolver, marca como ❌ e não faz push. Quando desativada, conflitos são apenas reportados.notes.conflictBranches), escalar no relatório com seção dedicada "🔴 Conflitos persistentes" e recomendar ação: dropar o PR, recriar a branch, ou resolver manualmente. O ciclo é incrementado a cada execução onde o conflito reaparece, mesmo que a resolução automática tenha sido tentada e falhado.review-closed para decisão do usuáriofull-sync, patches com review vencida são apresentados ao usuário para reavaliaçãolocal/ para distinguir de branches de PR (ex: local/my-custom-fix). A branch original pode ser renomeada ou mantida — o importante é que o config rastreie a branch corretaAntes de qualquer operação que troca de branch ou deleta/recria branches (especialmente build-production e full-sync), sempre verificar e preservar arquivos unstaged, untracked e staged:
cd <localPath>
# 1. Checar se há arquivos em risco
git status --porcelain
# 2. Se houver arquivos modificados/untracked, fazer stash com untracked
git stash push --include-untracked -m "fork-manager: pre-sync stash $(date -u +%Y%m%dT%H%M%S)"
# 3. Executar a operação (rebase, checkout, merge, etc.)
# ...
# 4. Após concluir, restaurar o stash
git stash pop
Por quê? Ao deletar e recriar a branch de produção (git branch -D <productionBranch>), arquivos que existiam apenas no working directory (não commitados) são perdidos permanentemente. Isso inclui:
Regra: Se git status --porcelain retornar qualquer saída, fazer git stash --include-untracked antes de prosseguir. Restaurar com git stash pop ao final.
This skill performs operations that require broad filesystem and network access by design:
Before using this skill on a repository:
--force-with-lease (not --force) to prevent data lossThese capabilities are inherent to fork management and cannot be removed without breaking core functionality.
User: "sync my fork of project-x"
Agent:
$SKILL_DIR/repos/project-x/config.jsonstatus to assess current statesyncrebase-allproductionBranch if neededUser: "/fork-manager --auto-resolve" or "/fork-manager full-sync --auto-resolve"
Agent:
rebase-all:build-production with resolved branches