Saltar para o conteúdo principal
O Fast Apply é o motor local que transforma uma edição da IA em uma mudança real no disco. Os modelos premium planejam e o modelo local embutido (o Forge) descreve a mudança, mas é o Fast Apply que de fato funde essa mudança no seu arquivo. Ele roda inteiramente na sua máquina, não custa nada em tokens de API e segue regras rígidas para nunca escrever algo do qual não tenha certeza. Esta página explica como o Fast Apply analisa as edições, como localiza o ponto certo no seu arquivo, por que recusa edições ambíguas e como ele se combina com o Forge para manter as mudanças de código baratas e seguras.

Determinístico por design

O app aplica a edição, nunca o modelo. A mesma entrada sempre produz a mesma saída.

Local e gratuito

A fusão roda no processo principal do Electron, sem chamada externa por padrão.

Nunca reescreve arquivos inteiros

Apenas os trechos correspondentes mudam. Todo o resto do seu arquivo é preservado byte a byte.

Falha em alto e bom som, nunca adivinha

Se uma correspondência for ambígua ou inexistente, a edição é rejeitada com um motivo claro.

Por que um motor determinístico

Modelos locais pequenos são ótimos em descrever uma mudança, mas pouco confiáveis em reproduzir longos trechos de código literalmente. Se você deixar o modelo reescrever um arquivo inteiro, ele tende a remover comentários, reordenar imports ou alterar silenciosamente código distante da edição. O Fast Apply elimina esse risco ao tornar o modelo responsável apenas pelo texto da mudança, enquanto o app é responsável por onde e como esse texto é inserido.
O modelo só produz o texto da edição. O aplicador (parseEditBlocks, applyEditBlocks e mergeLazyEdit em src/main/services/smart-exec/morph.ts) é o que altera o seu arquivo. Essa separação é o que torna cada aplicação reproduzível e revisável.

Os dois formatos de edição

O Fast Apply entende dois formatos de edição. Ambos mantêm o modelo honesto ao forçá-lo a se ancorar em linhas que realmente existem no seu arquivo.
Um bloco nomeia as linhas exatas a encontrar e as linhas a colocar no lugar delas:
<<<<<<< SEARCH
<existing lines, exact>
=======
<new lines>
>>>>>>> REPLACE
Regras:
  • São permitidos vários blocos por arquivo, aplicados em ordem.
  • Um SEARCH vazio significa inserir ou criar: o REPLACE é prependido ao arquivo (ou se torna o arquivo inteiro se ele estava vazio).
  • Um REPLACE vazio significa excluir: as linhas correspondentes ao SEARCH são removidas.
  • Cada bloco deve corresponder exatamente uma vez. Mais de uma correspondência é rejeitada como ambígua.
O formato preguiçoso é o que o Forge mais usa. Ele mantém a saída do modelo curta, que é exatamente onde os modelos pequenos são mais precisos, e permite que o app preserve cada linha que o modelo não mencionou.

Como funciona uma fusão de busca e substituição

Quando o Fast Apply processa um bloco de busca e substituição, ele percorre os níveis do mais rígido ao mais tolerante e para no primeiro nível que produz uma correspondência única e não ambígua.
1

Analisar os blocos

parseEditBlocks varre a saída do modelo em busca das marcações SEARCH, ======= e REPLACE. O texto em prosa ao redor dos blocos é ignorado, marcações soltas de código markdown são removidas e blocos truncados (sem um divisor ou marcador final) são descartados em vez de aplicados pela metade.
2

Tentar uma correspondência exata

O motor conta as ocorrências do texto SEARCH no arquivo. Exatamente uma ocorrência é substituída no local. Zero ou mais de uma passa para a próxima decisão.
3

Rejeitar correspondências ambíguas

Se o texto SEARCH aparece mais de uma vez, a edição é rejeitada com um motivo como SEARCH matches 3x (ambiguous), needs more context. O Fast Apply não escolherá um entre vários pontos por você.
4

Tentar uma correspondência com espaços normalizados

Se não houve acerto exato, o motor compara o SEARCH com janelas de linhas do mesmo tamanho, com os espaços finais e internos normalizados. Ele aplica a mudança apenas quando exatamente uma janela é equivalente.
5

Tentar uma correspondência aproximada ancorada e segura

Como último recurso, ele pontua cada janela de mesmo tamanho por similaridade. Ele aplica apenas quando exatamente uma janela atinge ou supera o limiar de similaridade. Isso captura quase-acertos por espaços ou aspas sem nunca adivinhar.
6

Falhar claramente se nada se encaixar

Se nenhum nível produz uma correspondência única, o bloco falha com um motivo preciso. O orquestrador pode então reparar a edição ou escalar para um modelo premium, em vez de corromper o seu arquivo.
O nível aproximado usa um limiar de similaridade fixo de 0.92 e só dispara para uma única janela qualificada. Zero ou múltiplas janelas acima do limiar significam rejeição. Essa barra é deliberadamente alta para que o motor possa absorver variações de espaços e aspas, mas nunca possa escrever silenciosamente o conteúdo errado.

Como funciona uma fusão preguiçosa

As edições preguiçosas são fundidas por mergeLazyEdit. A atualização é dividida em trechos a cada marcador de reticências, e cada trecho é costurado de volta ao seu arquivo usando suas linhas de âncora.
1

Segmentar a atualização

A atualização é dividida em trechos contíguos sempre que aparece um marcador ... existing code .... O marcador é reconhecido em vários estilos de comentário, então //, #, --, /* */, <!-- --> e ; todos funcionam.
2

Escolher as âncoras

Para cada trecho, a primeira e a última linha não vazias se tornam as âncoras inicial e final. As linhas de borda vazias são ignoradas porque corresponderiam a qualquer linha vazia.
3

Localizar as âncoras no seu arquivo

anchorPositions busca cada âncora do mais rígido ao mais tolerante: linha exata, linha sem espaços nas pontas, depois linha com espaços normalizados. Se essas falharem, ele tenta uma chave estrutural para declarações comuns de JS e TS (de modo que export default function foo ainda possa se ancorar em export function foo quando esse nome é único), depois uma única linha aproximada de alta similaridade. Linhas curtas como } ou ) nunca são correspondidas de forma aproximada.
4

Escolher o melhor trecho

Quando vários pares de âncoras são possíveis, o motor escolhe o trecho cujo comprimento é mais próximo do comprimento do snippet. Isso evita o bug clássico de fechar na primeira } aninhada em vez da verdadeira chave de fechamento da função.
5

Preservar tudo fora do trecho

As linhas originais antes de cada trecho (o cabeçalho e os espaços entre trechos) e depois do último trecho (o final) são copiadas inalteradas. Apenas os trechos correspondentes são substituídos.
6

Proteger contra encolhimento catastrófico

Após a fusão, se um arquivo não trivial (mais de 30 linhas) perdeu mais de 60 por cento das suas linhas, a fusão é rejeitada como âncora suspeita, em vez de gravar um arquivo mutilado.
Em uma fusão preguiçosa, as linhas de âncora reais do seu arquivo são mantidas, não as versões reformatadas pelo modelo. Assim, mesmo quando o modelo ajusta o espaçamento de uma âncora, a linha exata do seu arquivo sobrevive à fusão.

Por que a ambiguidade é rejeitada

Todo o motor é construído sobre uma promessa: se não tiver certeza, não escreve. Essa promessa aparece em vários lugares.
Quando um SEARCH ou âncora corresponde mais de uma vez, o motor recusa em vez de escolher. Uma escolha errada editaria a região errada e passaria pela revisão sem ser notada. A rejeição força uma edição mais específica ou uma escalada.
Cada correspondedor tenta primeiro o exato, depois o sem espaços nas pontas, depois o normalizado. O primeiro nível que encontra qualquer correspondência vence, então uma correspondência exata nunca é diluída por correspondências mais frouxas abaixo.
A correspondência por similaridade só se aplica com uma única janela acima de um limiar alto. Ela existe para absorver ruído de espaços e aspas, não para inventar conteúdo.
Toda rejeição carrega um motivo legível: correspondência ambígua, âncora não encontrada ou encolhimento suspeito. Esse motivo é o que permite ao orquestrador decidir reparar ou escalar.

Como o Fast Apply se combina com o Forge

O Forge é o modelo local embutido (Qwen2.5-Coder) que executa as mudanças de código. O Fast Apply são as mãos dele. O Forge escreve uma edição preguiçosa; o Fast Apply a funde de forma determinística; só se a fusão não conseguir encontrar suas âncoras é que o trabalho sobe um nível.
1

Um modelo premium planeja

Um orquestrador premium lê o seu repositório e decide o que deve mudar, depois delega a edição concreta ao Forge.
2

O Forge emite uma edição

O Forge produz uma edição preguiçosa curta (ou blocos de busca e substituição), mantendo apenas algumas linhas de âncora ao redor de cada mudança.
3

O Fast Apply funde localmente

O aplicador determinístico funde a edição no seu arquivo com custo zero de API. A maioria das edições se resolve aqui.
4

Escalar apenas em caso de falha

Se a fusão local não conseguir ancorar a edição, o trabalho é escalado para que um modelo premium produza uma edição mais limpa, em vez de o motor adivinhar.
Existe um fallback hospedado opcional (morphFastApply, a API do morphllm.com) que pode fundir uma edição preguiçosa antes da escalada para premium. Ele vem desligado por padrão e só ativa quando uma MORPH_API_KEY está presente no ambiente. Ele não é exposto na UI, porque o Orkestral é local-first.

O que fazer a seguir

Conheça o Forge

Aprenda como o modelo local embutido executa mudanças de código com custo zero de API.

Revisar mudanças

Veja como as edições fundidas aparecem como diffs que você pode aprovar antes de chegarem ao seu repositório.

Configurar ferramentas

Gerencie o comportamento do Fast Apply e provedores opcionais na área de Ferramentas.

Como funciona a orquestração

Entenda como planejamento, delegação e execução se encaixam.