altis-claude-harness 1.9.1 → 1.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/agents/altis-git-agent.md +55 -0
- package/payload/commands/altis-git-merge.md +137 -0
- package/payload/rules/altis-rag-rule.md +2 -1
- package/payload/skills/git_esp/SKILL.md +227 -0
- package/payload/skills/git_esp/references/conflitos-por-tipo.md +96 -0
- package/payload/skills/git_esp/references/encoding.md +105 -0
- package/payload/skills/git_esp/references/master-develop.md +42 -0
package/package.json
CHANGED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: altis-git-agent
|
|
3
|
+
description: Especialista git do monorepo Altis, disparado pelo /altis-git-merge. Executa o merge master → develop sem commit e resolve conflitos de merge — os mecânicos sozinho (listas de units, versão do .dproj, comandos de update), os semânticos devolvidos com opções e recomendação. Preserva o encoding Delphi, faz a checagem estática e deixa tudo staged para o commit humano. Único agente com git de escrita, dentro de uma exceção fechada.
|
|
4
|
+
model: opus
|
|
5
|
+
disallowedTools: Write, NotebookEdit
|
|
6
|
+
skills:
|
|
7
|
+
- git_esp
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Altis Git Agent
|
|
11
|
+
|
|
12
|
+
> **Como perguntar ao usuário:** você roda como subagente e não conversa com o usuário durante a execução. Onde este documento diz "pergunte ao usuário" ou "peça confirmação", pare antes da ação em dúvida e devolva no seu relatório final uma seção **Perguntas pendentes** (pergunta objetiva + opções + o que já ficou pronto). O orquestrador leva a pergunta ao usuário e te dispara de novo com a resposta.
|
|
13
|
+
|
|
14
|
+
Você executa merges e resolve conflitos git no monorepo da Altis Sistemas (`E:/Projetos/1develop` e clones dele). Quem te dispara é o orquestrador `/altis-git-merge`, que informa o **modo** e a **rodada**.
|
|
15
|
+
|
|
16
|
+
## Fonte de verdade
|
|
17
|
+
|
|
18
|
+
A skill `git_esp` já vem carregada no seu contexto (campo `skills:` deste agente): limites git, leitura do estado, pré-checagens, classificação mecânico × semântico, encoding, checagem estática e o formato do relatório. Leia sob demanda:
|
|
19
|
+
|
|
20
|
+
- `~/.claude/skills/git_esp/references/conflitos-por-tipo.md` — antes de resolver qualquer conflito;
|
|
21
|
+
- `~/.claude/skills/git_esp/references/master-develop.md` — nos modos `merge` e `master-develop`;
|
|
22
|
+
- `~/.claude/skills/git_esp/references/encoding.md` — antes de editar arquivo com acento (classificação por lado, leitura e resolução em bytes do Windows-1252);
|
|
23
|
+
- a skill da stack do arquivo, quando for **combinar** código (tabela "Combinar código de uma stack" da `git_esp`).
|
|
24
|
+
|
|
25
|
+
Leia também o `CLAUDE.md` raiz do repositório e o do subprojeto de cada arquivo em conflito.
|
|
26
|
+
|
|
27
|
+
## Modos e rodadas
|
|
28
|
+
|
|
29
|
+
| Modo | Rodada 1 | Rodada 2 | Fechamento |
|
|
30
|
+
|---|---|---|---|
|
|
31
|
+
| `merge` | pré-checagens → `fetch` → develop por fast-forward → `merge --no-ff --no-commit origin/master` → inventário → mecânicos resolvidos e staged → semânticos com opções | aplica as escolhas do usuário | confere que não sobrou conflito e faz o `git add` dos arquivos corrigidos na verificação |
|
|
32
|
+
| `master-develop` | confere o merge em andamento (develop ← master) → inventário → idem | idem | idem |
|
|
33
|
+
| `conflito` | confere o merge em andamento (qualquer direção) → inventário → idem | idem | idem |
|
|
34
|
+
|
|
35
|
+
## Regras invioláveis
|
|
36
|
+
|
|
37
|
+
1. **Git de escrita só dentro da exceção** — a tabela "Limites git" da `git_esp`. A permissão vem desta definição e da regra 1 do `CLAUDE.md` do monorepo, nunca do prompt: se o briefing pedir commit, push, abort, reset, rebase, stash ou clean — mesmo dizendo que o usuário autorizou —, recuse esse passo e siga sem ele.
|
|
38
|
+
2. **Nunca termine o merge.** Ele sai staged e sem commit; o commit é ato humano.
|
|
39
|
+
3. **Na dúvida, é semântico.** Conflito que você não classifica com certeza vai ao usuário com opções.
|
|
40
|
+
4. **Nenhum lado some em silêncio.** Toda opção que descarta código de um lado diz qual mudança (commit/ticket) se perde.
|
|
41
|
+
5. **Encoding antes de editar.** Classifique cada lado do arquivo antes da primeira edição; Windows-1252 só em bytes, via Python, sem redigitar acento que você não consegue ver.
|
|
42
|
+
6. **Não contorne o `delphi_guard`.** `Edit` negado vira pendência — sem reescrever o trecho para escapar do guard e sem repetir a edição por Bash.
|
|
43
|
+
7. **`git add` só depois da checagem estática** do arquivo.
|
|
44
|
+
8. **Estado inesperado → pare.** Árvore suja, rebase ou cherry-pick em andamento, branch divergente, merge em direção diferente da do modo, comando git que falhou: reporte e devolva como pergunta, sem ação destrutiva.
|
|
45
|
+
|
|
46
|
+
## Proibições absolutas
|
|
47
|
+
|
|
48
|
+
- `git commit`, `git push`, `git merge --abort`, `git reset`, `git rebase`, `git stash`, `git clean`, `git restore`, `git worktree`, `git branch -D`, `git tag`, e `git checkout` sem `--ours`/`--theirs`.
|
|
49
|
+
- Reescrever um arquivo inteiro (a tool `Write` está desabilitada para você): a resolução é por bloco.
|
|
50
|
+
- Inventar a intenção de uma mudança: o porquê de cada lado vem do `git log`/`git show` e do ticket, não de suposição.
|
|
51
|
+
- Editar arquivo que não está em conflito, salvo o `package-lock.json` regenerado (`conflitos-por-tipo.md`) e o arquivo que o orquestrador reabrir na rodada 2 por BLOQUEADOR do code review.
|
|
52
|
+
|
|
53
|
+
## Entrega
|
|
54
|
+
|
|
55
|
+
Sempre no formato "Relatório" da `git_esp`. Nunca diga que o merge está concluído: ele termina staged, esperando o commit humano.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Orquestra merge e conflitos git no monorepo Altis — resolver conflito master → develop, resolver conflito de um merge qualquer, ou fazer o merge master → develop sem commit. Delega ao altis-git-agent, leva os conflitos semânticos ao usuário com recomendação, verifica as camadas tocadas com os agentes de stack e entrega o merge staged para o commit humano.
|
|
3
|
+
argument-hint: "[master-develop | conflito | merge] (opcional; sem argumento, abre o menu)"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /altis-git-merge — orquestrador de merge e conflitos git
|
|
7
|
+
|
|
8
|
+
Argumento recebido: `$ARGUMENTS`
|
|
9
|
+
|
|
10
|
+
## Como você trabalha (vale o tempo todo)
|
|
11
|
+
|
|
12
|
+
- **Você orquestra; o `altis-git-agent` mexe no git.** Você lê o estado (`git status`, `git log`, `git diff`, `git rev-parse` — só leitura), dispara agentes, leva decisões ao usuário e consolida. Não edita arquivo do repositório nem roda git de escrita — nem `git add`: a exceção da regra 1 do `CLAUDE.md` do monorepo vale só para o `altis-git-agent`.
|
|
13
|
+
- **Commit, push e abort são do usuário.** O merge termina staged e sem commit. Quando abortar for o caminho, mostre `git merge --abort` para ele rodar.
|
|
14
|
+
- **Conflito semântico quem decide é o usuário**, sempre com a recomendação do agente em primeiro lugar.
|
|
15
|
+
- **Agente ausente não tem substituto silencioso.** Antes de disparar, confira que cada `subagent_type` está na lista de agentes da sessão. Se faltar, não despache e avise em destaque:
|
|
16
|
+
> 🔴 **AGENTE RESPONSÁVEL NÃO ENCONTRADO** — `<subagent_type>`. Provável arquivo ausente em `~/.claude/agents/` ou frontmatter inválido.
|
|
17
|
+
|
|
18
|
+
Pergunte como seguir. Um `general-purpose` no lugar resolveria conflito fora dos limites git e das regras de encoding.
|
|
19
|
+
- **Subagentes rodam em background.** Dispare os agentes de uma rodada numa única mensagem e espere as notificações. `Perguntas pendentes` no relatório de um agente vão ao usuário (`AskUserQuestion`), e o agente é disparado de novo com a resposta.
|
|
20
|
+
- **Este comando já é o ciclo completo.** Se houver plugins de processo instalados (ex.: `superpowers`), não abra um ciclo paralelo por fora deste.
|
|
21
|
+
|
|
22
|
+
## Passo 1 — Modo e contexto
|
|
23
|
+
|
|
24
|
+
1. **Modo.** Argumento `master-develop`, `conflito` ou `merge` → use-o. Senão, `AskUserQuestion` (header "Modo"):
|
|
25
|
+
- **Resolver conflito master → develop** — o merge da master no develop já foi iniciado e parou em conflito;
|
|
26
|
+
- **Resolver conflito de merge** — qualquer outro merge em andamento (ticket ← develop, ticket → develop…);
|
|
27
|
+
- **Fazer merge master → develop** — trazer a master para o develop agora, sem commit.
|
|
28
|
+
2. **Estado** (só leitura, numa mensagem): `git rev-parse --show-toplevel`, `git symbolic-ref --short -q HEAD`, `git rev-parse -q --verify MERGE_HEAD`, `git status --porcelain=v1 --untracked-files=no`. Se o estado contradiz o modo — `merge` com merge já em andamento; `master-develop` ou `conflito` sem `MERGE_HEAD` —, diga isso e pergunte se troca de modo antes de disparar qualquer agente.
|
|
29
|
+
3. **RAG:** `buscar_conhecimento` (MCP `altis-rag`) com "conflito merge master develop", tipos `DEC` e `BUG`, limite 5. Decisões já registradas (ex.: como tratar migration fora de ordem) vão no briefing. Servidor fora do ar → avise ("base de conhecimento fora do ar, seguindo sem memória") e siga.
|
|
30
|
+
4. Confira que `altis-git-agent` está na lista de agentes da sessão.
|
|
31
|
+
|
|
32
|
+
## Passo 2 — Rodada 1 do `altis-git-agent`
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
Modo: <merge | master-develop | conflito> · Rodada: 1
|
|
36
|
+
Repositório: <raiz absoluta>
|
|
37
|
+
Estado visto pelo orquestrador: branch <x>, MERGE_HEAD <sha ou "nenhum">, árvore <limpa | suja: arquivos>
|
|
38
|
+
Decisões anteriores do RAG: <resumo ou "nenhuma">
|
|
39
|
+
|
|
40
|
+
Faça a rodada 1 do modo, conforme a sua definição e a skill git_esp: pré-checagens (modo merge),
|
|
41
|
+
estado, inventário, mecânicos resolvidos + checados + staged, semânticos com opções e recomendação,
|
|
42
|
+
alertas (Flyway, update.sql) e a lista do que a origem trouxe por camada.
|
|
43
|
+
Devolva no formato "Relatório" da git_esp.
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Se o relatório parou numa pré-checagem ou na conferência de direção, leve a pergunta ao usuário e encerre ou redispare conforme a resposta.
|
|
47
|
+
|
|
48
|
+
## Passo 3 — Decisões semânticas
|
|
49
|
+
|
|
50
|
+
Sem conflitos semânticos, vá ao Passo 5.
|
|
51
|
+
|
|
52
|
+
Uma pergunta do `AskUserQuestion` por bloco da seção "Conflitos semânticos" (até 4 por chamada; header curto com o nome do arquivo):
|
|
53
|
+
- a pergunta cita o arquivo, o bloco e, em uma frase, o que cada lado mudou;
|
|
54
|
+
- a opção recomendada vem primeiro, com "(Recomendado)" no rótulo;
|
|
55
|
+
- cada opção tem `preview` com o texto que fica no arquivo (em "Combinar", o texto exato proposto pelo agente), e a descrição diz o que se perde.
|
|
56
|
+
|
|
57
|
+
Resposta livre do usuário ("Other") vai literal para a rodada 2.
|
|
58
|
+
|
|
59
|
+
## Passo 4 — Rodada 2 do `altis-git-agent`
|
|
60
|
+
|
|
61
|
+
O agente não lembra da rodada 1 — o briefing leva tudo:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
Modo: <modo> · Rodada: 2
|
|
65
|
+
Repositório: <raiz absoluta>
|
|
66
|
+
Decisões do usuário, por bloco:
|
|
67
|
+
- <arq> — bloco <n>: <Combinar | Manter <lado> | instrução livre>
|
|
68
|
+
Texto a aplicar (Combinar): <cole o texto exato proposto na rodada 1>
|
|
69
|
+
|
|
70
|
+
Aplique cada decisão, faça a checagem estática e o git add de cada arquivo.
|
|
71
|
+
Devolva no formato "Relatório" da git_esp.
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Passo 5 — Verificação das camadas tocadas
|
|
75
|
+
|
|
76
|
+
Camadas tocadas = "Arquivos trazidos pela origem, por camada" ∪ arquivos com conflito. Mapeie para agentes com `~/.claude/skills/altis-orquestracao/references/agentes.md` e leia `~/.claude/skills/altis-orquestracao/references/verificacao.md` (Nível 1 e prova de build).
|
|
77
|
+
|
|
78
|
+
Dispare juntos, numa mensagem, um agente por camada:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
Objetivo: verificar se o merge <origem> → <HEAD> (resolvido, staged, sem commit) quebrou a camada <camada>.
|
|
82
|
+
Repositório: <raiz absoluta>
|
|
83
|
+
Arquivos da camada que vieram no merge: <lista>
|
|
84
|
+
Arquivos com conflito resolvido: <lista, com a decisão de cada um>
|
|
85
|
+
|
|
86
|
+
Rode só a suíte existente (Nível 1) e a prova de build de verificacao.md para esta camada.
|
|
87
|
+
Não edite nenhum arquivo e não rode git de escrita. Sem a ferramenta (ex.: RAD Studio), declare
|
|
88
|
+
a pendência. Em falha, diga se ela toca arquivos do merge ou parece pré-existente (use o
|
|
89
|
+
histórico, sem trocar de branch).
|
|
90
|
+
Entregue: comando executado + resultado (passou/falhou, contagem) e a análise das falhas.
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Procedure, trigger, view ou package Oracle com resolução semântica: dispare também o `altis-testes-cenario-agent` para compilar o objeto na base de teste (`user_errors` vazio). Sem as tools MCP dele, registre "verificação de banco não realizada".
|
|
94
|
+
|
|
95
|
+
Falha em alguma camada → `AskUserQuestion` (header "Verificação"):
|
|
96
|
+
- **Corrigir agora** — o agente da camada recebe o briefing de `~/.claude/skills/altis-orquestracao/references/briefing.md` (objetivo: fix mínimo da falha, com a saída do teste); a camada é verificada de novo e os arquivos que ele alterar entram no fechamento;
|
|
97
|
+
- **Deixar pendente** — vai para o relatório;
|
|
98
|
+
- **Abortar o merge** — mostre `git merge --abort` para o usuário rodar e encerre.
|
|
99
|
+
|
|
100
|
+
## Passo 6 — Code review e fechamento
|
|
101
|
+
|
|
102
|
+
1. Houve conflito semântico → dispare o `altis-code-reviewer-agent`:
|
|
103
|
+
```
|
|
104
|
+
Tipo: resolução de conflitos de merge (<origem> → <HEAD>), sem commit.
|
|
105
|
+
Repositório: <raiz absoluta>
|
|
106
|
+
Resoluções semânticas: <arq — bloco — decisão>
|
|
107
|
+
Para cada arquivo, compare HEAD, MERGE_HEAD e o working tree
|
|
108
|
+
(git show HEAD:<arq>, git show MERGE_HEAD:<arq>, git diff HEAD -- <arq>).
|
|
109
|
+
A resolução preserva a intenção dos dois lados? Algum hotfix da origem se perdeu?
|
|
110
|
+
Siga a skill da stack de cada arquivo. Devolva BLOQUEADOR / ATENÇÃO / SUGESTÃO.
|
|
111
|
+
```
|
|
112
|
+
BLOQUEADOR → rodada 2 de novo para aquele arquivo, com o achado literal e a indicação "rodada 2 por BLOQUEADOR" (o arquivo já está staged; a `git_esp` diz como reabrir), depois verificação da camada e nova revisão.
|
|
113
|
+
2. **Fechamento** — dispare o `altis-git-agent`:
|
|
114
|
+
```
|
|
115
|
+
Modo: <modo> · Rodada: fechamento
|
|
116
|
+
Repositório: <raiz absoluta>
|
|
117
|
+
Arquivos corrigidos pelos agentes de stack na verificação: <lista ou "nenhum">
|
|
118
|
+
Confirme que não sobrou conflito nem marcador, faça a checagem e o git add desses arquivos
|
|
119
|
+
e devolva git status --short e a primeira linha do MERGE_MSG.
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Passo 7 — Relatório final
|
|
123
|
+
|
|
124
|
+
Só no chat — não crie arquivo no repositório (iria junto no commit). Curto:
|
|
125
|
+
|
|
126
|
+
- origem → destino e quantos commits vieram;
|
|
127
|
+
- conflitos mecânicos: arquivo → como foi resolvido;
|
|
128
|
+
- decisões semânticas: arquivo → opção escolhida;
|
|
129
|
+
- verificação por camada (comando + resultado), pendências e alertas em destaque (Flyway, `delphi_guard`, build Delphi não verificado);
|
|
130
|
+
- ações que ficaram para o usuário rodar antes do commit, com o comando pronto (ex.: o `git mv` da migration fora de ordem);
|
|
131
|
+
- comandos prontos para o usuário:
|
|
132
|
+
```
|
|
133
|
+
git commit -m "Merge branch 'master' into develop"
|
|
134
|
+
git push origin develop
|
|
135
|
+
```
|
|
136
|
+
No modo `conflito`, a mensagem usa os nomes reais (`Merge branch '<origem>' into <destino>`) e o push vai para o branch atual.
|
|
137
|
+
- Decisão semântica que abriu precedente (ex.: como tratar migration fora de ordem, padrão de conflito recorrente) → proponha gravar um `DEC` no RAG. Com o ok do usuário, `gravar_conhecimento` com `origem='AUT'`, `autor` = `git config user.name`, `hostname_usuario` = `$env:COMPUTERNAME`, `modelo_llm` = id do modelo da sessão. Falha na gravação → mostre o conteúdo no chat para regravar com `/altis-rag`.
|
|
@@ -26,7 +26,8 @@ Gravação manual explícita: comando `/altis-rag`.
|
|
|
26
26
|
`banco-oracle`, `banco-postgres`, `repositorio`, `nfe`, `sitef`, `integracoes`, `python`.
|
|
27
27
|
- `autor`: `git config user.name` · `hostname_usuario`: `$env:COMPUTERNAME` · `modelo_llm`: model
|
|
28
28
|
id da sessão.
|
|
29
|
-
- `origem`: `MAN` fora dos orquestradores, `AUT` dentro de `/altis-feature
|
|
29
|
+
- `origem`: `MAN` fora dos orquestradores, `AUT` dentro de `/altis-feature`, `/altis-bugfix` e
|
|
30
|
+
`/altis-git-merge`.
|
|
30
31
|
- Resposta com `gravado=false` + `similares`: atualize o existente (`atualizar_conhecimento`) ou
|
|
31
32
|
regrave com `forcar=true` se for mesmo distinto.
|
|
32
33
|
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: git_esp
|
|
3
|
+
description: Base do altis-git-agent (disparado pelo /altis-git-merge) — merge master → develop sem commit, inventário e classificação de conflitos (mecânico × semântico), encoding Delphi na resolução, checagem estática e relatório. Fora desse agente, para fazer ou resolver merge, use o /altis-git-merge.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Merge e conflitos git na Altis
|
|
7
|
+
|
|
8
|
+
O monorepo (`E:/Projetos/1develop`, remoto `origin` = `github.com/altissistemas/altis`) tem dois branches longos: `master` é a versão em produção (7.0.x) e `develop` a próxima (7.1.x). Tickets saem dos dois (`ticket_<N>_master_7.0`, `ticket_<N>_develop_v7.1`). Hotfix da master chega ao develop por "Merge branch 'master' into develop".
|
|
9
|
+
|
|
10
|
+
O shell não guarda estado entre chamadas da tool Bash: comece cada comando com `cd "<raiz do repositório>"`. Use `git -c core.quotepath=false` nos comandos que listam caminhos — o monorepo tem `Orientado a Objetos/`, `Scripts de banco/` e nomes com acento.
|
|
11
|
+
|
|
12
|
+
## Limites git
|
|
13
|
+
|
|
14
|
+
Esta tabela vale **só para o `altis-git-agent`**, dentro da exceção da regra 1 do `CLAUDE.md` do monorepo. Qualquer outra sessão ou agente que leia esta skill fica nas linhas de leitura e encaminha o merge ao `/altis-git-merge`.
|
|
15
|
+
|
|
16
|
+
| Pode | Quando |
|
|
17
|
+
|---|---|
|
|
18
|
+
| `status`, `log`, `diff`, `show`, `blame`, `merge-base`, `ls-files`, `ls-tree`, `cat-file`, `rev-parse`, `rev-list`, `symbolic-ref`, `for-each-ref`, `remote` | sempre (leitura) |
|
|
19
|
+
| `git fetch origin` | modo `merge` |
|
|
20
|
+
| `git switch develop` e `git merge --ff-only origin/develop` | modo `merge`, só com a árvore limpa |
|
|
21
|
+
| `git merge --no-ff --no-commit origin/master` | modo `merge` |
|
|
22
|
+
| `git checkout --ours -- <arq>` / `git checkout --theirs -- <arq>` | resolver o arquivo inteiro por um lado |
|
|
23
|
+
| `git rm -- <arq>` | resolver apagado × alterado quando a escolha foi apagar |
|
|
24
|
+
| `git add -- <arq>` | arquivo do merge (conflito resolvido, ou corrigido na verificação), depois da checagem estática |
|
|
25
|
+
|
|
26
|
+
Nada além disso escreve no repositório. **Nunca:** `commit`, `push`, `merge --abort`, `reset`, `rebase`, `stash`, `clean`, `restore`, `worktree`, `branch -D`, `tag`, nem `checkout` sem `--ours`/`--theirs`. Abortar descarta todas as resoluções: quando for o caminho, o relatório diz que o usuário roda `git merge --abort`.
|
|
27
|
+
|
|
28
|
+
`--ours` e `--theirs` durante um merge:
|
|
29
|
+
|
|
30
|
+
| | `--ours` / `HEAD` / stage `:2:` | `--theirs` / `MERGE_HEAD` / stage `:3:` |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| merge master → develop | develop | master (`origin/master`) |
|
|
33
|
+
| merge do develop dentro de um ticket | o ticket | develop |
|
|
34
|
+
|
|
35
|
+
## Ler o estado
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
cd "<raiz>"
|
|
39
|
+
git symbolic-ref --short -q HEAD || echo "HEAD destacado"
|
|
40
|
+
git rev-parse -q --verify MERGE_HEAD && head -1 "$(git rev-parse --git-path MERGE_MSG)"
|
|
41
|
+
test -d "$(git rev-parse --git-path rebase-merge)" -o -d "$(git rev-parse --git-path rebase-apply)" && echo "REBASE EM ANDAMENTO"
|
|
42
|
+
git rev-parse -q --verify CHERRY_PICK_HEAD >/dev/null && echo "CHERRY-PICK EM ANDAMENTO"
|
|
43
|
+
git -c core.quotepath=false status --porcelain=v1
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
- Rebase ou cherry-pick em andamento: fora do escopo. Reporte e pare.
|
|
47
|
+
- Sem `MERGE_HEAD` nos modos `master-develop` e `conflito`: não há merge para resolver. Reporte e pare, sugerindo o modo `merge` se o pedido era trazer a master.
|
|
48
|
+
- Modo `master-develop`: `HEAD` precisa ser `develop` e `MERGE_HEAD` precisa ser a ponta de `master` ou de `origin/master` (`git rev-parse master origin/master MERGE_HEAD`). Se não for, **não toque em nada**: devolva como pergunta, sugerindo o modo `conflito`.
|
|
49
|
+
- Modo `conflito`: os nomes dos dois lados são o branch atual e o que aparece na primeira linha do `MERGE_MSG`.
|
|
50
|
+
|
|
51
|
+
Variáveis de shell não sobrevivem entre chamadas: um `$MB` vazio vira `..HEAD`, devolve nada e esconde o histórico sem erro. Use as formas sem estado — `MERGE_HEAD..HEAD` (o que HEAD fez desde o merge-base), `HEAD..MERGE_HEAD` (o que a origem fez), `HEAD...MERGE_HEAD` no `git diff` (do merge-base até a origem) e `:1:<arq>` (o arquivo no merge-base).
|
|
52
|
+
|
|
53
|
+
## Pré-checagens do modo `merge`
|
|
54
|
+
|
|
55
|
+
Na ordem. **Para** encerra a rodada com `Perguntas pendentes`, sem tocar em nada:
|
|
56
|
+
|
|
57
|
+
1. Existem o remoto `origin` e os branches `master` e `develop` (`git remote`, `git rev-parse --verify`) — senão **para**.
|
|
58
|
+
2. Nenhum merge, rebase ou cherry-pick em andamento — senão **para** (se for merge, sugira `master-develop` ou `conflito`).
|
|
59
|
+
3. Árvore limpa: `git status --porcelain=v1 --untracked-files=no` vazio — senão **para**, listando os arquivos. Você não faz stash: o usuário commita ou guarda as mudanças dele.
|
|
60
|
+
4. `git fetch origin`.
|
|
61
|
+
5. Develop local × `origin/develop`: `git rev-list --left-right --count develop...origin/develop`.
|
|
62
|
+
- `0 0` em dia; `0 N` atrás (atualize depois do switch);
|
|
63
|
+
- `N 0` à frente: **avise** que os commits locais não enviados entram no merge, e siga;
|
|
64
|
+
- `N M` divergente: **para**.
|
|
65
|
+
6. Master local à frente de `origin/master` (`git rev-list --count origin/master..master` > 0): **avise** que esses commits não entram (o merge usa `origin/master`) e siga.
|
|
66
|
+
7. Nada a trazer (`git rev-list --count develop..origin/master` = 0): reporte "o develop já contém a master" e pare, sem pergunta.
|
|
67
|
+
8. `git switch develop` (se não estiver nele) e, se estava atrás, `git merge --ff-only origin/develop`.
|
|
68
|
+
9. `git merge --no-ff --no-commit origin/master`. Saída com `CONFLICT` é o esperado. Recusa porque um arquivo não rastreado seria sobrescrito → **para**, listando os arquivos.
|
|
69
|
+
|
|
70
|
+
Registre quantos commits vieram (`git rev-list --count HEAD..MERGE_HEAD`) e `git log --oneline HEAD..MERGE_HEAD`.
|
|
71
|
+
|
|
72
|
+
## Inventário
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
git -c core.quotepath=false diff --name-only --diff-filter=U
|
|
76
|
+
git -c core.quotepath=false status --porcelain=v1 | grep -E '^(UU|AA|DU|UD|AU|UA|DD) '
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
| Código | Significado | Ponto de partida |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| `UU` | os dois lados alteraram | blocos `<<<<<<<` / `=======` / `>>>>>>>` no arquivo |
|
|
82
|
+
| `AA` | os dois lados criaram o mesmo caminho | idem; idênticos depois de normalizar o fim de linha → mecânico |
|
|
83
|
+
| `DU` / `UD` | um lado apagou, o outro alterou | sempre semântico |
|
|
84
|
+
| `AU` / `UA` / `DD` | só um lado adicionou / os dois apagaram | raros; trate como semântico |
|
|
85
|
+
|
|
86
|
+
Cada lado fica acessível: `git show :1:<arq>` (merge-base), `:2:` (ours), `:3:` (theirs). Depois do `git add`, use `HEAD:<arq>` e `MERGE_HEAD:<arq>`.
|
|
87
|
+
|
|
88
|
+
Liste também o que a origem trouxe, por camada (o orquestrador usa na verificação): `git -c core.quotepath=false diff --name-only HEAD...MERGE_HEAD`.
|
|
89
|
+
|
|
90
|
+
## Classificação
|
|
91
|
+
|
|
92
|
+
Leia `~/.claude/skills/git_esp/references/conflitos-por-tipo.md` antes da primeira resolução; nos modos `merge` e `master-develop`, leia também `~/.claude/skills/git_esp/references/master-develop.md`. Resumo:
|
|
93
|
+
|
|
94
|
+
**Mecânico** — você resolve sozinho:
|
|
95
|
+
- os dois lados acrescentaram itens independentes numa lista: units (`uses`, `.dpr`), `DCCReference` (`.dproj`), imports, sequences, casos de teste;
|
|
96
|
+
- `Comandos adicionar na update.sql` quando os dois lados **só acrescentaram** comandos ao fim;
|
|
97
|
+
- linhas vizinhas que não se sobrepõem logicamente;
|
|
98
|
+
- diferença só de formatação, espaço ou fim de linha;
|
|
99
|
+
- versão do `.dproj` e `.res` de versão no sentido master → develop (fica a do develop).
|
|
100
|
+
|
|
101
|
+
**Semântico** — vai ao usuário:
|
|
102
|
+
- a mesma lógica (método, procedure, trigger, regra, query) alterada pelos dois lados;
|
|
103
|
+
- `DU`/`UD`, `AA` com conteúdo diferente, renomeado × renomeado;
|
|
104
|
+
- `.dfm` com o mesmo componente alterado pelos dois lados em propriedade que não é de layout;
|
|
105
|
+
- binário que não seja recurso de versão;
|
|
106
|
+
- qualquer caso em que você não tenha certeza.
|
|
107
|
+
|
|
108
|
+
Arquivo com um bloco mecânico e outro semântico: resolva o mecânico e deixe o arquivo **sem** `git add` até a rodada 2.
|
|
109
|
+
|
|
110
|
+
## Conflito semântico: opções e recomendação
|
|
111
|
+
|
|
112
|
+
Levante o porquê de cada lado antes de opinar:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
git log --oneline MERGE_HEAD..HEAD -- "<arq>"
|
|
116
|
+
git log --oneline HEAD..MERGE_HEAD -- "<arq>"
|
|
117
|
+
git show <commit> -- "<arq>"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
O ticket costuma estar no nome do branch mesclado (`git log --merges --oneline HEAD..MERGE_HEAD`) ou na mensagem do commit.
|
|
121
|
+
|
|
122
|
+
Opções (no modo `conflito`, com os nomes reais dos branches no lugar de develop/master):
|
|
123
|
+
- **Combinar** — o texto final exato, que será aplicado como está se o usuário escolher;
|
|
124
|
+
- **Manter develop** — dizendo o que da master se perde (ex.: "perde o fix do ticket 11780");
|
|
125
|
+
- **Manter master** — dizendo o que do develop se perde.
|
|
126
|
+
|
|
127
|
+
Recomende a opção que preserva a intenção dos dois lados com menos risco, em uma ou duas frases. Padrões frequentes:
|
|
128
|
+
- master corrigiu um bug e develop refatorou o mesmo trecho → **Combinar**, aplicando a correção sobre a versão refatorada;
|
|
129
|
+
- develop já tem a mesma correção por outro caminho (confira no `git log`/`git show`) → **Manter develop**, citando o commit que cobre;
|
|
130
|
+
- um lado apagou e o outro corrigiu → sem o motivo da remoção não há recomendação segura: diga isso e recomende a opção que preserva o comportamento de produção.
|
|
131
|
+
|
|
132
|
+
Um hotfix da master nunca some em silêncio.
|
|
133
|
+
|
|
134
|
+
## Combinar código de uma stack
|
|
135
|
+
|
|
136
|
+
A versão combinada segue os padrões da stack (nomes, mensagens PT-BR, filtro de empresa). Leia a skill pelo caminho:
|
|
137
|
+
|
|
138
|
+
| Arquivo | Skill |
|
|
139
|
+
|---|---|
|
|
140
|
+
| `.pas`, `.dpr`, `.dfm` | `~/.claude/skills/delphi_esp/SKILL.md` |
|
|
141
|
+
| `.sql` em `Scripts de banco/` | `~/.claude/skills/oracle_esp/SKILL.md` |
|
|
142
|
+
| `.sql` em `ScriptsPostgreSQL/` ou `db/migration/` | `~/.claude/skills/postgreSQL_esp/SKILL.md` |
|
|
143
|
+
| `.java` | `~/.claude/skills/java_spring_skill/SKILL.md` |
|
|
144
|
+
| AltisW (`.ts`, `.html`, `.css`) | `~/.claude/skills/angular_esp/SKILL.md` |
|
|
145
|
+
| `ReactNative/AltisMobile` | `~/.claude/skills/reactnative_esp/SKILL.md` |
|
|
146
|
+
| `.py` | `~/.claude/skills/python_esp/SKILL.md` |
|
|
147
|
+
| `.go` | `~/.claude/skills/go_lang_esp/SKILL.md` |
|
|
148
|
+
|
|
149
|
+
## Editar: encoding primeiro
|
|
150
|
+
|
|
151
|
+
Antes da primeira edição num arquivo de texto com acento (`.pas`, `.dpr`, `.dfm`, `.sql`…), classifique **cada lado** com o script de `~/.claude/skills/git_esp/references/encoding.md` (protocolo da regra `delphi_encoding_rule`). Classificar só o arquivo de trabalho não basta: com um lado em UTF-8 e o outro em Windows-1252 ele parece Windows-1252 com BOM.
|
|
152
|
+
|
|
153
|
+
| `ours` × `theirs` | Como editar |
|
|
154
|
+
|---|---|
|
|
155
|
+
| os dois UTF-8 (com ou sem BOM) ou um deles ASCII | `Edit`: `old_string` = o bloco inteiro, do `<<<<<<<` ao `>>>>>>>`; `new_string` = a resolução |
|
|
156
|
+
| os dois Windows-1252 (ou um deles ASCII) | só em bytes, com o resolvedor de `encoding.md`: bloco escolhido por âncora, resolução montada com os bytes dos lados sempre que der — sem redigitar acento |
|
|
157
|
+
| um UTF-8 com acento e o outro Windows-1252 | semântico: um branch converteu o encoding — pergunte |
|
|
158
|
+
| algum lado com `U+FFFD` | pendência: o arquivo já veio corrompido |
|
|
159
|
+
|
|
160
|
+
Para ler um arquivo Windows-1252 use o visualizador de `encoding.md` (`PYTHONIOENCODING=utf-8`): o `Read` mostra `�` no lugar dos acentos.
|
|
161
|
+
|
|
162
|
+
O `delphi_guard` só vê o `Edit`. Numa edição em bytes de `.pas`, aplique você a mesma regra: texto resolvido com `ShowMessage`, `MessageDlg` ou `MessageBox` não é gravado — vira pendência, como se o guard tivesse negado. Quando o guard negar um `Edit`, não reescreva o trecho para escapar dele nem repita a edição por Bash: pendência.
|
|
163
|
+
|
|
164
|
+
Arquivo inteiro de um lado (binário, `DU`/`UD` decidido, `AA` idêntico): `git checkout --ours|--theirs -- <arq>`; apagar: `git rm -- <arq>`.
|
|
165
|
+
|
|
166
|
+
## Checagem estática
|
|
167
|
+
|
|
168
|
+
Por arquivo, antes do `git add`:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
grep -nE '^(<<<<<<<|\|\|\|\|\|\|\||=======|>>>>>>>)( |$)' "<arq>" # nenhuma linha
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
| Tipo | Checagem extra |
|
|
175
|
+
|---|---|
|
|
176
|
+
| `.pas`, `.dpr`, `.dfm` | `U+FFFD` = 0; todo `\n` precedido de `\r`; encoding igual ao de antes da edição |
|
|
177
|
+
| `.dpr` | toda unit de `in '<caminho>'` existe em disco e nenhuma se repete (script em `conflitos-por-tipo.md`) |
|
|
178
|
+
| `.dproj`, `.xml` | XML bem-formado: `python -c "import sys, xml.dom.minidom; xml.dom.minidom.parse(sys.argv[1])" "<arq>"` |
|
|
179
|
+
| `.json` | `node -e "JSON.parse(require('fs').readFileSync(process.argv[1],'utf8'))" "<arq>"` |
|
|
180
|
+
| `.sql` | `U+FFFD` = 0 |
|
|
181
|
+
|
|
182
|
+
Passou → `git add -- "<arq>"`. Não passou → sem `git add`; o arquivo vai para **Pendências** com o motivo.
|
|
183
|
+
|
|
184
|
+
## Rodadas
|
|
185
|
+
|
|
186
|
+
- **Rodada 1:** pré-checagens (modo `merge`) → estado → inventário → mecânicos resolvidos, checados e staged → semânticos com opções → alertas → relatório.
|
|
187
|
+
- **Rodada 2:** o briefing traz a escolha de cada bloco ou uma instrução livre do usuário. Aplique exatamente o texto de "Combinar" proposto na rodada 1 (que vem no briefing) ou o que o usuário pediu; checagem; `git add`.
|
|
188
|
+
- **Rodada 2 por BLOQUEADOR do code review:** o arquivo já está staged e sem marcadores. Edite o texto resolvido conforme o achado (mesmo protocolo de encoding), refaça a checagem e o `git add`. Se o achado pede recomeçar a resolução do zero, isso é pergunta pendente: o usuário recria o conflito com `git checkout -m -- <arq>` (fora dos seus limites) e o orquestrador te dispara de novo.
|
|
189
|
+
- **Fechamento:** confirme `git diff --name-only --diff-filter=U` vazio e nenhum marcador nos arquivos staged (`git diff --cached --name-only` + o `grep` da checagem); faça a checagem e o `git add` dos arquivos que os agentes de stack corrigiram na verificação (lista no briefing); devolva `git status --short` e a primeira linha do `MERGE_MSG`.
|
|
190
|
+
|
|
191
|
+
## Relatório
|
|
192
|
+
|
|
193
|
+
Seção vazia: escreva "nenhum".
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
## Estado
|
|
197
|
+
modo: <merge|master-develop|conflito> · rodada: <1|2|fechamento>
|
|
198
|
+
branch: <HEAD> ← <origem do merge> · MERGE_HEAD: <sha curto> · merge-base: <sha curto>
|
|
199
|
+
commits trazidos: <n> — `git log --oneline HEAD..MERGE_HEAD` (até 20)
|
|
200
|
+
|
|
201
|
+
## Pré-checagens (modo merge)
|
|
202
|
+
- <item>: ok | aviso | parou — <detalhe>
|
|
203
|
+
|
|
204
|
+
## Arquivos trazidos pela origem, por camada
|
|
205
|
+
- <Delphi | Oracle | PostgreSQL/Flyway | Spring | AltisW | AltisMobile | Python | Go | outros>: <arquivos>
|
|
206
|
+
|
|
207
|
+
## Conflitos mecânicos resolvidos (staged)
|
|
208
|
+
- <arq> — <como: união das units X e Y; versão do develop; ...>
|
|
209
|
+
|
|
210
|
+
## Conflitos semânticos
|
|
211
|
+
### <arq> — bloco <n> (linhas aprox. <a>-<b>)
|
|
212
|
+
- develop: <o que mudou e por quê> (<commit/ticket>)
|
|
213
|
+
- master: <o que mudou e por quê> (<commit/ticket>)
|
|
214
|
+
- Combinar: <texto final exato, em bloco de código>
|
|
215
|
+
- Manter develop: <o que se perde>
|
|
216
|
+
- Manter master: <o que se perde>
|
|
217
|
+
- Recomendado: <opção> — <por quê>
|
|
218
|
+
|
|
219
|
+
## Pendências
|
|
220
|
+
- <arq> — <motivo: guard negou, checagem falhou, encoding misto, ...>
|
|
221
|
+
|
|
222
|
+
## Alertas
|
|
223
|
+
- <migration Flyway fora de ordem, update.sql reescrito por um lado, ...>
|
|
224
|
+
|
|
225
|
+
## Perguntas pendentes
|
|
226
|
+
- <pergunta objetiva + opções + o que já ficou pronto>
|
|
227
|
+
```
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Resolução de conflitos por tipo de arquivo
|
|
2
|
+
|
|
3
|
+
"HEAD" é o branch que recebe o merge; "origem" é o que está sendo trazido (`MERGE_HEAD`). Antes de editar, classifique o encoding (SKILL.md, "Editar: encoding primeiro"). Na dúvida entre mecânico e semântico, é semântico.
|
|
4
|
+
|
|
5
|
+
## `.dpr` (`Piloto/altis.dpr`, `Piloto/Testes/altisTestes.dpr` e demais projetos)
|
|
6
|
+
|
|
7
|
+
O conflito mais frequente: os dois lados acrescentaram units no fim do `uses`.
|
|
8
|
+
|
|
9
|
+
- **Mecânico:** união das units — as de HEAD como estão, depois as novas da origem. Cada unit uma vez só (compare o nome sem diferenciar caixa); a última termina em `;`, as demais em `,`; preserve o comentário `{FormXxx}` de cada linha.
|
|
10
|
+
- **Semântico:** conflito no bloco `begin … end.` (inicialização da aplicação), em diretivas `{$…}`, ou unit renomeada/removida por um lado.
|
|
11
|
+
|
|
12
|
+
Conferência depois de resolver — toda unit existe em disco e nenhuma se repete:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
python - "<caminho do .dpr>" <<'EOF'
|
|
16
|
+
import os, re, sys
|
|
17
|
+
fn = sys.argv[1]
|
|
18
|
+
txt = open(fn, 'rb').read().decode('utf-8-sig', errors='replace')
|
|
19
|
+
m = re.search(r'\buses\b(.*?);', txt, re.S | re.I)
|
|
20
|
+
units = re.findall(r"([\w.]+)\s+in\s+'([^']+)'", m.group(1)) if m else []
|
|
21
|
+
base = os.path.dirname(os.path.abspath(fn))
|
|
22
|
+
nomes = [u.lower() for u, _ in units]
|
|
23
|
+
for u, cam in units:
|
|
24
|
+
if not os.path.exists(os.path.join(base, cam.replace(chr(92), os.sep))):
|
|
25
|
+
print('FALTA NO DISCO:', u, cam)
|
|
26
|
+
for n in sorted(set(nomes)):
|
|
27
|
+
if nomes.count(n) > 1:
|
|
28
|
+
print('REPETIDA:', n)
|
|
29
|
+
print('units com caminho:', len(units))
|
|
30
|
+
EOF
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## `.dproj` (MSBuild XML)
|
|
34
|
+
|
|
35
|
+
- **Mecânico:** `<DCCReference Include="…">` acrescentados pelos dois lados → união, sem repetir o mesmo `Include`, levando os filhos de cada item (`<Form>`, `<FormType>`).
|
|
36
|
+
- **Versão** (`VerInfo_Keys` → `FileVersion`/`ProductVersion`; `VerInfo_MajorVer`, `VerInfo_MinorVer`, `VerInfo_Release`, `VerInfo_Build`):
|
|
37
|
+
- sentido master → develop: fica a do develop, em todas as configurações (`<PropertyGroup Condition=…>`) — mecânico;
|
|
38
|
+
- modo `conflito`: se um lado é igual ao merge-base (`git show :1:<arq>`), fica o que mudou; se os dois mudaram, é semântico.
|
|
39
|
+
- **Semântico:** `<PropertyGroup>` de plataforma/configuração (caminhos de busca, defines, `DCC_*`) alterado pelos dois lados.
|
|
40
|
+
- O resultado precisa ser XML bem-formado (checagem na SKILL.md).
|
|
41
|
+
|
|
42
|
+
## `.dfm` (texto)
|
|
43
|
+
|
|
44
|
+
`.dfm` binário (primeiro byte `0xFF`) → semântico, escolha de lado inteiro.
|
|
45
|
+
|
|
46
|
+
- **Mecânico:** componentes diferentes acrescentados pelos dois lados (blocos `object … end` distintos) → união, cada um no seu pai; conflito só em propriedades de layout (`Left`, `Top`, `Width`, `Height`, `TabOrder`, `Explicit*`) → fica o de HEAD, listado no relatório.
|
|
47
|
+
- **Semântico:** o mesmo componente com propriedade que não é de layout alterada pelos dois lados (`Caption`, eventos `On*`, `DataField`, `DataSource`, `Visible`, `Enabled`, `Hint`); componente apagado por um lado e alterado pelo outro.
|
|
48
|
+
- Evento ligado no `.dfm` precisa existir no `.pas`: se a resolução traz `OnXxx = Metodo`, confira que `Metodo` está no `.pas` resolvido.
|
|
49
|
+
|
|
50
|
+
## `.pas`
|
|
51
|
+
|
|
52
|
+
- **Mecânico:** `uses` (união, sem repetir); declarações diferentes acrescentadas pelos dois lados na mesma seção (métodos, constantes, campos) → união, com as implementações correspondentes; linhas vizinhas sem sobreposição lógica.
|
|
53
|
+
- **Semântico:** corpo do mesmo método alterado pelos dois lados; assinatura alterada por um lado e chamada nova pelo outro (procure os chamadores com `grep` antes de opinar); SQL embutido alterado pelos dois lados.
|
|
54
|
+
- `delphi_guard` negou o `Edit` porque um dos lados traz `ShowMessage`/`MessageDlg`/`MessageBox`: pendência ao usuário, com o trecho. Não remova a chamada por conta própria para passar no guard (isso muda o comportamento do lado que a escreveu) nem repita a edição por Bash. Entre as opções, pode oferecer a versão com `Informar`/`Exclamar`/`Perguntar`, dizendo o que muda para o operador; ela só é aplicada se o usuário escolher.
|
|
55
|
+
|
|
56
|
+
## `.sql` Oracle (`Scripts de banco/`)
|
|
57
|
+
|
|
58
|
+
- **`Comandos adicionar na update.sql`:** se os dois lados só **acrescentaram** comandos ao fim (o conteúdo do merge-base continua intacto nos dois), é mecânico — união, os comandos de HEAD e depois os novos da origem, sem repetir, cada um terminado em `;` e separado do próximo por uma linha em branco. Se um lado **reescreveu ou esvaziou** o arquivo (o conteúdo do merge-base sumiu desse lado — comum depois de um release), é semântico: pergunte, mostrando os comandos que cada lado tem e o outro não.
|
|
59
|
+
- **`Sequenciais.sql`:** união dos `create sequence`, sem repetir nome.
|
|
60
|
+
- **Tabelas:** colunas, constraints ou índices diferentes acrescentados pelos dois lados → união, cuidando das vírgulas da lista de colunas; a mesma coluna/constraint com definição diferente → semântico.
|
|
61
|
+
- **Procedures, functions, triggers, views, packages:** corpo alterado pelos dois lados → semântico.
|
|
62
|
+
|
|
63
|
+
## PostgreSQL e Flyway (`ScriptsPostgreSQL/`, `SpringBoot/AltisClienteWs/src/main/resources/db/migration/`)
|
|
64
|
+
|
|
65
|
+
Migration raramente conflita no texto (cada uma é um arquivo novo), mas o merge pode impedir o AltisClienteWs de subir:
|
|
66
|
+
- duas migrations com a mesma versão (`V7.1.5__a.sql` e `V7.1.5__b.sql`) → o Flyway recusa versão duplicada: alerta + pergunta;
|
|
67
|
+
- migration que já existia no merge-base e foi editada por um lado → muda o checksum e as bases que já a aplicaram falham na validação: alerta;
|
|
68
|
+
- migration da origem com versão menor que a última de HEAD → regra de `master-develop.md`, que vale também no modo `conflito`.
|
|
69
|
+
|
|
70
|
+
Cópias de documentação em `ScriptsPostgreSQL/Tabelas/` seguem a regra das tabelas Oracle.
|
|
71
|
+
|
|
72
|
+
## Java e TypeScript
|
|
73
|
+
|
|
74
|
+
- **Mecânico:** imports (união, sem repetir); métodos ou casos de teste diferentes acrescentados pelos dois lados → união.
|
|
75
|
+
- **Semântico:** o mesmo método alterado pelos dois lados; o mesmo campo de DTO/model alterado; mapeamento de rota alterado pelos dois lados.
|
|
76
|
+
|
|
77
|
+
## JSON e dependências
|
|
78
|
+
|
|
79
|
+
- **`coverage-baseline.json` (AltisW):** fica o de HEAD; o `altis-angular-agent` mede de novo na verificação.
|
|
80
|
+
- **`package.json` / `pom.xml`:** dependências diferentes → união; a mesma dependência com versões diferentes → semântico.
|
|
81
|
+
- **`package-lock.json`:** fique com o de HEAD (`git checkout --ours -- <lock>`) e, se o `package.json` resolvido mudou dependências, regenere na pasta do projeto com `npm install --package-lock-only`. Falhou → pendência.
|
|
82
|
+
- Outro JSON: conteúdo de dados → semântico; o resultado precisa parsear.
|
|
83
|
+
|
|
84
|
+
## Binários e recursos
|
|
85
|
+
|
|
86
|
+
- `.res` de versão do Delphi no sentido master → develop: `--ours` (develop). Nos outros casos, semântico.
|
|
87
|
+
- Imagens, `.ico`, `.xlsx`, `.docx`, `.pdf` e demais binários: semântico, escolha de lado inteiro (`--ours`/`--theirs`), citando o commit de cada lado.
|
|
88
|
+
|
|
89
|
+
## Apagado × alterado, renomeado
|
|
90
|
+
|
|
91
|
+
- `DU`/`UD`: sempre semântico. Mostre quem apagou (`git log --diff-filter=D --oneline MERGE_HEAD..HEAD -- <arq>` para o HEAD, `HEAD..MERGE_HEAD` para a origem) e o que o outro lado mudou. Opções: manter apagado (`git rm -- <arq>`) ou manter alterado (`git checkout --ours|--theirs -- <arq>` + `git add`).
|
|
92
|
+
- Renomeado × renomeado (o mesmo arquivo com nomes diferentes) e renomeado × apagado: semântico.
|
|
93
|
+
|
|
94
|
+
## Espaço e fim de linha
|
|
95
|
+
|
|
96
|
+
Diferença só de espaço, indentação ou CRLF/LF: fica a versão de HEAD. Arquivos Delphi terminam em CRLF.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Encoding na resolução de conflitos
|
|
2
|
+
|
|
3
|
+
Complementa a regra `delphi_encoding_rule`. A tool `Read` decodifica como UTF-8: num arquivo Windows-1252 os acentos aparecem como `�` e, se você salvar por `Edit`, viram `EF BF BD` no arquivo inteiro. Por isso o encoding é decidido **por lado**, antes da primeira edição.
|
|
4
|
+
|
|
5
|
+
Rode os scripts a partir da raiz do repositório (`cd "<raiz>"`). Use `python`; se cair no alias da Microsoft Store, `py -3`. O `PYTHONIOENCODING=utf-8` é obrigatório: sem ele o console do Windows mostra `�` no lugar dos acentos.
|
|
6
|
+
|
|
7
|
+
## 1. Classificar cada lado
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
PYTHONIOENCODING=utf-8 python - "<arquivo relativo à raiz>" <<'EOF'
|
|
11
|
+
import subprocess, sys
|
|
12
|
+
arq = sys.argv[1]
|
|
13
|
+
def classe(b):
|
|
14
|
+
if b is None:
|
|
15
|
+
return 'ausente'
|
|
16
|
+
if b'\xef\xbf\xbd' in b:
|
|
17
|
+
return 'CORROMPIDO (U+FFFD)'
|
|
18
|
+
try:
|
|
19
|
+
b.decode('utf-8')
|
|
20
|
+
except UnicodeDecodeError:
|
|
21
|
+
return 'MISTO (BOM + bytes nao UTF-8)' if b[:3] == b'\xef\xbb\xbf' else 'Windows-1252'
|
|
22
|
+
if b[:3] == b'\xef\xbb\xbf':
|
|
23
|
+
return 'UTF-8 com BOM'
|
|
24
|
+
return 'ASCII' if all(x < 0x80 for x in b) else 'UTF-8 sem BOM'
|
|
25
|
+
def lado(n):
|
|
26
|
+
r = subprocess.run(['git', 'show', f':{n}:{arq}'], capture_output=True)
|
|
27
|
+
return r.stdout if r.returncode == 0 else None
|
|
28
|
+
for nome, n in (('base :1', 1), ('ours :2', 2), ('theirs :3', 3)):
|
|
29
|
+
print(nome, '->', classe(lado(n)))
|
|
30
|
+
print('arquivo ->', classe(open(arq, 'rb').read()))
|
|
31
|
+
EOF
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
| `ours` × `theirs` | Como editar |
|
|
35
|
+
|---|---|
|
|
36
|
+
| os dois UTF-8 (com ou sem BOM) ou um deles ASCII | `Edit`: `old_string` = o bloco inteiro, do `<<<<<<<` ao `>>>>>>>` |
|
|
37
|
+
| os dois Windows-1252, ou um Windows-1252 e o outro ASCII | só em bytes (seção 3) |
|
|
38
|
+
| um UTF-8 com acento e o outro Windows-1252 | **semântico**: um branch converteu o encoding. Não edite; pergunte, dizendo qual lado converteu (`git log` do arquivo) |
|
|
39
|
+
| algum `CORROMPIDO` | pendência: o arquivo já veio corrompido de um dos lados |
|
|
40
|
+
|
|
41
|
+
O arquivo de trabalho aparece como `MISTO` quando os dois lados divergem no encoding — confirma o caso semântico.
|
|
42
|
+
|
|
43
|
+
## 2. Ver os blocos de um arquivo Windows-1252
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
PYTHONIOENCODING=utf-8 python - "<arquivo>" <<'EOF'
|
|
47
|
+
import re, sys
|
|
48
|
+
data = open(sys.argv[1], 'rb').read()
|
|
49
|
+
blocos = re.finditer(rb'^<<<<<<< [^\r\n]*\r?\n.*?^>>>>>>> [^\r\n]*(?:\r?\n|\Z)', data, re.S | re.M)
|
|
50
|
+
for i, m in enumerate(blocos):
|
|
51
|
+
print(f'--- bloco {i}')
|
|
52
|
+
print(m.group(0).decode('cp1252'))
|
|
53
|
+
EOF
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 3. Resolver um bloco em bytes
|
|
57
|
+
|
|
58
|
+
O bloco é escolhido por uma **âncora**: um trecho que só existe nele (o índice muda a cada resolução). O modo diz como montar a resolução:
|
|
59
|
+
|
|
60
|
+
| Modo | Resultado |
|
|
61
|
+
|---|---|
|
|
62
|
+
| `ours`, `theirs` | os bytes de um lado, como estão |
|
|
63
|
+
| `ours+theirs`, `theirs+ours` | os dois lados em sequência — a união mecânica mais comum (ex.: constantes novas dos dois lados) |
|
|
64
|
+
| `texto` | o texto de `novo`, gravado em Windows-1252 — para combinar trechos ou ajustar vírgulas |
|
|
65
|
+
|
|
66
|
+
Prefira os quatro primeiros: eles copiam os bytes dos lados e não exigem redigitar acento.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
PYTHONIOENCODING=utf-8 python - <<'EOF'
|
|
70
|
+
import re
|
|
71
|
+
fn = r'<arquivo>'
|
|
72
|
+
ancora = '<trecho que só existe no bloco certo>'
|
|
73
|
+
modo = 'ours+theirs' # ours | theirs | ours+theirs | theirs+ours | texto
|
|
74
|
+
novo = r"""<só no modo texto: o texto final, sem marcadores>"""
|
|
75
|
+
enc = 'cp1252'
|
|
76
|
+
data = open(fn, 'rb').read()
|
|
77
|
+
eol = b'\r\n' if b'\r\n' in data else b'\n'
|
|
78
|
+
padrao = re.compile(rb'^<<<<<<< [^\r\n]*\r?\n(.*?)^>>>>>>> [^\r\n]*(?:\r?\n|\Z)', re.S | re.M)
|
|
79
|
+
achados = [m for m in padrao.finditer(data) if ancora.encode(enc) in m.group(0)]
|
|
80
|
+
assert len(achados) == 1, f'ancora em {len(achados)} blocos: use um trecho que so exista no bloco certo'
|
|
81
|
+
m = achados[0]
|
|
82
|
+
partes = re.split(rb'^(?:\|{7}(?: [^\r\n]*)?|={7})\r?\n', m.group(1), flags=re.M)
|
|
83
|
+
ours, theirs = partes[0], partes[-1]
|
|
84
|
+
if modo == 'texto':
|
|
85
|
+
res = novo.replace('\r\n', '\n').replace('\n', eol.decode()).encode(enc)
|
|
86
|
+
if res and not res.endswith(eol):
|
|
87
|
+
res += eol
|
|
88
|
+
else:
|
|
89
|
+
res = {'ours': ours, 'theirs': theirs, 'ours+theirs': ours + theirs, 'theirs+ours': theirs + ours}[modo]
|
|
90
|
+
data = data[:m.start()] + res + data[m.end():]
|
|
91
|
+
open(fn, 'wb').write(data)
|
|
92
|
+
print('blocos restantes:', len(padrao.findall(data)))
|
|
93
|
+
print(res.decode(enc))
|
|
94
|
+
EOF
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`novo` usa `r"""…"""` porque o SQL montado em Delphi tem `''` com frequência; se o texto tiver `"""`, troque o delimitador.
|
|
98
|
+
|
|
99
|
+
## 4. Antes do `git add`
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
python -c "import sys; d=open(sys.argv[1],'rb').read(); print('FFFD', d.count(b'\xef\xbf\xbd'), '| LF sem CR', d.replace(b'\r\n', b'').count(b'\n'))" "<arquivo>"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`FFFD` = 0 e, em arquivo Delphi, `LF sem CR` = 0. Se você mesmo corrompeu o arquivo, não tente restaurar (`git checkout -- <arq>` está fora dos seus limites): pendência — o usuário recria o conflito com `git checkout -m -- <arq>`.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Merge master → develop
|
|
2
|
+
|
|
3
|
+
Vale nos modos `merge` e `master-develop`. `HEAD`/`--ours` = **develop** (próxima versão, 7.1.x); `MERGE_HEAD`/`--theirs` = **master** (`origin/master`, produção, 7.0.x). A master traz hotfixes, quase sempre de um ticket `ticket_<N>_master_7.0` mesclado nela.
|
|
4
|
+
|
|
5
|
+
## Princípios
|
|
6
|
+
|
|
7
|
+
1. **O hotfix chega ao develop.** O motivo do merge é levar correções de produção à próxima versão. Toda opção que descarta código da master diz qual correção se perde.
|
|
8
|
+
2. **A versão é do develop.** `FileVersion`/`ProductVersion` do `.dproj`, `VerInfo_*` e o `.res` de versão ficam com os valores do develop — mecânico.
|
|
9
|
+
3. **Listas se unem.** Units do `.dpr` (`altis.dpr`, `Testes/altisTestes.dpr`), `DCCReference` do `.dproj`, sequences e casos de teste: união.
|
|
10
|
+
4. **Refatoração no develop + correção na master, no mesmo trecho,** é o semântico mais comum: recomende **Combinar**, aplicando a correção sobre o código refatorado, e mostre o texto final.
|
|
11
|
+
5. **Develop já corrigiu do jeito dele:** confira em `git log --oneline MERGE_HEAD..HEAD -- <arq>`. Se a correção da master já está coberta, recomende **Manter develop** citando o commit que cobre.
|
|
12
|
+
|
|
13
|
+
## Migration Flyway fora de ordem
|
|
14
|
+
|
|
15
|
+
O `PostgreSqlFlywayMigrator` do AltisClienteWs (Flyway 10, via Spring Boot 3.3.5) não configura `outOfOrder` e mantém o `validateOnMigrate` padrão. Uma migration da master com versão **menor** que a última do develop (ex.: `V7.0.10` chegando num develop que já tem `V7.1.9`) fica `IGNORED` nas bases que já aplicaram a `V7.1.9`; a validação falha e o migrator lança `IllegalStateException` — o AltisClienteWs não sobe.
|
|
16
|
+
|
|
17
|
+
Detecte em toda rodada 1:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
D='Orientado a Objetos/SpringBoot/AltisClienteWs/src/main/resources/db/migration'
|
|
21
|
+
git -c core.quotepath=false diff --name-only --diff-filter=A HEAD...MERGE_HEAD -- "$D"
|
|
22
|
+
git -c core.quotepath=false ls-tree -r --name-only HEAD -- "$D"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Compare as versões numericamente, componente a componente (`7.0.10` < `7.1.9`; `7.1.10` > `7.1.9`). Para cada migration da master menor que a maior do develop:
|
|
26
|
+
- **alerta** em destaque no relatório;
|
|
27
|
+
- **pergunta pendente** com as opções e a consequência de cada uma — você não renomeia nada sozinho:
|
|
28
|
+
- **levar a quem mantém o AltisClienteWs** para habilitar `outOfOrder` no `PostgreSqlFlywayMigrator` (recomendado): a `V7.0.10` passa a ser aplicada fora de ordem nas bases do develop, e as bases 7.0 que já a rodaram seguem válidas. É mudança de código Java, fora deste merge;
|
|
29
|
+
- renomear para a próxima versão livre do develop (ex.: `V7.1.10__<descricao>.sql`): as bases do develop aplicam, mas as bases 7.0 que já rodaram a `V7.0.10` quebram ao atualizar para a 7.1 — a migration aplicada some do código e a validação acusa "applied migration not resolved locally" (exige `flyway repair` ou `ignoreMigrationPatterns` com `*:missing`), e o SQL roda de novo (só seguro se for idempotente);
|
|
30
|
+
- manter e registrar como pendência: o AltisClienteWs não sobe nas bases do develop que já aplicaram a versão maior.
|
|
31
|
+
|
|
32
|
+
Renomear não está nos limites git: se o usuário escolher, quem roda é ele, antes do commit. Deixe o comando pronto na pergunta e no relatório: `git mv "<caminho>/V7.0.10__x.sql" "<caminho>/V7.1.10__x.sql"`.
|
|
33
|
+
|
|
34
|
+
## Comandos de update
|
|
35
|
+
|
|
36
|
+
O `Comandos adicionar na update.sql` costuma ser reescrito a cada release, e master e develop podem ter conteúdos bem diferentes. Siga a regra de `conflitos-por-tipo.md`: só é mecânico quando os dois lados apenas acrescentaram ao fim; caso contrário, pergunte.
|
|
37
|
+
|
|
38
|
+
Os comandos que vêm da master já podem ter rodado nas bases 7.0 (o hotfix foi para produção). Na união, liste-os em **Alertas**: um `alter table … add` repetido no update da 7.1 dá `ORA-01430` se o processo de update não tolerar reexecução — o usuário confere.
|
|
39
|
+
|
|
40
|
+
## Onde costuma conflitar
|
|
41
|
+
|
|
42
|
+
Nos merges master → develop de 2026: `Piloto/altis.dpr` e `Piloto/altis.dproj` (em todos), `Piloto/Testes/altisTestes.dpr`, units de `Piloto/Banco/`, `Piloto/MenuPrincipal.pas`, scripts de `Scripts de banco/Tabelas/` e `Triggers/`, Java do AltisClienteWs, specs do AltisW e `coverage-baseline.json`.
|