# JSON file editor — deterministic, token-free editing

> **A forma mais rápida e econômica de editar um arquivo é não usar um LLM para
> a edição em si.** Deixe o modelo decidir *o que* mudar e emitir um pequeno
> patch JSON; um executor determinístico aplica esse patch — sem chamada de
> modelo, sem tokens, em microssegundos, e 100% reproduzível.

## Por quê (a conta de custo)

| Critério | JSON / determinístico | LLM reescrevendo o arquivo |
|---|---|---|
| Custo | ~zero (CPU) | tokens de entrada (arquivo inteiro) + saída |
| Velocidade | µs–ms | centenas de ms a segundos |
| Confiabilidade | reproduzível; falha se o alvo sumiu | pode variar / alucinar |
| Quem decide o *quê* | gerado antes (LLM, script ou humano) | o próprio modelo |

A arquitetura mais barata é **híbrida**: o LLM emite o JSON uma vez (poucos
tokens de saída), e este executor aplica a edição. O modelo nunca precisa
"redigitar" o arquivo — o que economiza tokens e elimina o risco de corromper
trechos que não deveria tocar.

## Uso

### CLI

```bash
npx simplicio-edit edits.json              # aplica o script
cat edits.json | npx simplicio-edit -      # lê da stdin
npx simplicio-edit edits.json --dry-run    # pré-visualiza sem escrever
npx simplicio-edit edits.json --json       # relatório legível por máquina
npx simplicio-edit edits.json --cwd ./src  # resolve caminhos relativos
```

Códigos de saída: `0` sucesso · `1` erro de edição/validação · `2` erro de uso.

### Programático (ESM)

```js
import { applyEditScript, applyOps } from "simplicio-prompt/json-file-editor";

// camada de arquivo (toca o disco; honra dryRun)
const report = applyEditScript(script, { cwd: process.cwd(), dryRun: false });

// motor puro (string -> string), ideal para testes
const { text, applied } = applyOps("timeout: 30\n", [
  { op: "replace", find: "30", value: "60" },
]);
```

## Formato do script

```json
{
  "version": 1,
  "edits": [
    { "file": "config.yaml", "ops": [ /* ops de texto, em ordem */ ] },
    { "file": "novo.txt", "create": true, "content": "..." },
    { "file": "novo.txt", "create": true, "overwrite": true, "content": "..." },
    { "file": "antigo.txt", "delete": true }
  ]
}
```

Cada item de `edits` aponta para um `file` e faz **uma** de três coisas:
edita (`ops`), cria (`create`) ou apaga (`delete`).

## Operações de texto

| Op | Campos | Efeito |
|---|---|---|
| `replace` | `find`, `value`, `all?`, `optional?` | Substitui texto literal. Com mais de 1 ocorrência exige `"all": true`. |
| `regexReplace` | `find`, `value`, `flags?`, `optional?` | Substituição por regex (`flags` padrão `"g"`). |
| `insertAfter` | `find`, `value` | Insere uma linha após a primeira que contém `find`. |
| `insertBefore` | `find`, `value` | Insere uma linha antes da primeira que contém `find`. |
| `insertAtLine` | `line` (1-based), `value` | Insere na posição da linha. |
| `deleteLine` | `line` (1-based) | Remove a linha. |
| `deleteMatching` | `find` | Remove toda linha que contém `find`. |
| `append` | `value` | Acrescenta ao fim (insere `\n` se faltar). |
| `prepend` | `value` | Acrescenta no início. |

### Segurança por padrão

- **Sem adivinhação.** Se um `find` não casa, é erro — a menos que você passe
  `"optional": true`, e aí vira um no-op explícito.
- **Sem clobber acidental.** `create` em arquivo existente falha sem
  `"overwrite": true`.
- **`replace` ambíguo falha.** Mais de uma ocorrência sem `"all": true` é erro,
  evitando substituições não intencionais.
- **Newlines preservadas.** CRLF/LF do arquivo são respeitados.
- **`--dry-run`** calcula tudo e relata as mudanças sem tocar no disco.

## Exemplo executável

```bash
node examples/node/json-edit.mjs
```
