atomwrite 0.1.34

Atomic file operations CLI for LLM agents — read, write, edit, search, replace with NDJSON output
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
# Guia de Instalação

[Read in English](INSTALL.md)

- Instruções completas para instalar atomwrite em Linux, macOS e Windows
- Versão alvo atual: v0.1.34 (fuzzy one-shot, timeout padrão 120, exit 124 no prazo esgotado, recipes, sparse, semantic-merge, 41 subcomandos; builds slim/full por features)
- Seções ordenadas por plataforma, com pré-requisitos e solução de problemas


## O Que Há de Novo na v0.1.34

- Publicação docs-complete do runtime one-shot da v0.1.33 (mesmo comportamento do binário)
- Global `--timeout-secs` (alias `--timeout`) **padrão 120** (era 0); `0` desabilita; prazo esgotado → exit **124**
- Multi-apply fuzzy é **one-pass** E→D no conteúdo original (`apply_fuzzy_one_pass`); nunca reescaneia texto inserido
- Máximo de applies fuzzy padrão = **1** se `--max-replacements` omitido; teto rígido 10_000; embeds forçam apply único
- ADR-0054; suíte `cargo test --test cli_v0133_oneshot_fuzzy`
- Pin `^0.1.34` / 41 subcomandos

## O Que Há de Novo na v0.1.12

Esta seção resume as mudanças relevantes para instalação em v0.1.12.

### Instalação (Linux/macOS/Windows)

A release v0.1.12 é um substituto drop-in para v0.1.4. Instale com:

```bash
cargo install atomwrite --locked --version "^0.1.12"
```

O fix do Windows 10/11 de v0.1.4 é preservado (cargo install agora funciona). v0.1.12 adiciona:

- 6 novos subcomandos (`set`, `get`, `del`, `case`, `query`, `outline`) via implementação Tier 3 v14
- G72 verificação de sintaxe REAL via tree-sitter (24 linguagens via `tree-sitter-language-pack`)
- G114 sidecar WAL para recuperação de crash (consultivo, sem auto-replay)
- 5 novos códigos de erro (83 LockTimeout, 88 SyntaxError, 91 ExdevFallbackDisabled, 92 CopyBackBlake3Failed, 93 OrphanJournal)

### Nova Dependência

- `tree-sitter-language-pack = "1.8"` com features `download` + `dynamic-loading`
- Parsers baixam no primeiro uso (~5-10MB footprint total, não empacotados)
- Sem `cargo build` manual ou compilação de fonte necessária para suporte a linguagens

### Notas Específicas do Windows

- v0.1.12 preserva o fix do Windows da v0.1.4: `cargo install atomwrite` funciona no Windows 10/11.
- Melhorias no `init_console` (de v0.1.4) garantem que UTF-8 e sequências ANSI funcionem no Windows Terminal e PowerShell 7+.
- `persist_with_retry` lida com `PermissionDenied` durante rename atômico com backoff exponencial (compensação do Windows Defender).

### Notas Específicas do Linux

- v0.1.12 requer Rust 1.88 ou posterior (igual a v0.1.4).
- `cargo install atomwrite` do crates.io é o caminho de instalação recomendado.
- Sem dependências de nível de sistema além do toolchain Rust padrão.

### Notas Específicas do macOS

- v0.1.12 preserva os fixes de build do macOS arm64 (Apple Silicon) e macOS x86_64 da v0.1.2.
- Gatekeeper pode exigir `xattr -d com.apple.quarantine $(which atomwrite)` no primeiro uso.
- `posix_fadvise` é corretamente gateado a `cfg(target_os = "linux")` apenas (no-op no macOS).

### Cobertura de Testes

- 700+ testes listados (working tree v0.1.34; suíte `cli_v0133_oneshot_fuzzy`)
- ADRs em `docs/decisions/` até 0054
- 38 schemas JSON em `docs/schemas/`
- Veja [docs/decisions/README.md]decisions/README.md para decisões arquiteturais

## Linux

### Instalação Rápida (Ubuntu/Debian)

```bash
# Instalar Rust 1.88+ via rustup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"

# Instalar atomwrite v0.1.34 (path/fonte recomendado até o crates.io publicar)
cargo install --path . --locked --force
# Ou pin do crates.io quando 0.1.34 estiver publicada:
# cargo install atomwrite --locked --version "^0.1.34"

# Verificar
atomwrite --version
```

### Instalação Rápida (Fedora/RHEL)

```bash
# Instalar ferramentas de build
sudo dnf install rust cargo gcc

# Preferido: a partir do clone (v0.1.34)
cargo install --path . --locked --force
# Alternativa quando o crates.io publicar 0.1.34:
# cargo install atomwrite --locked --version "^0.1.34"
# Nota: o crates.io pode ainda listar versão mais antiga
```

### Instalação Rápida (Arch)

```bash
sudo pacman -S rust

# Preferido: a partir do clone (v0.1.34)
cargo install --path . --locked --force
# Alternativa quando o crates.io publicar 0.1.34:
# cargo install atomwrite --locked --version "^0.1.34"
# Nota: o crates.io pode ainda listar versão mais antiga
```


## macOS

### Instalação Rápida

```bash
# Instalar Rust 1.88+ via rustup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"

# Preferido: a partir do clone (v0.1.34)
cargo install --path . --locked --force
# Alternativa quando o crates.io publicar 0.1.34:
# cargo install atomwrite --locked --version "^0.1.34"
# Nota: o crates.io pode ainda listar versão mais antiga

# Liberar no Gatekeeper se solicitado
xattr -d com.apple.quarantine $(which atomwrite) 2>/dev/null || true
```


## Windows 10 / Windows 11

### Pré-Requisitos

1. **Rust 1.88 ou posterior** — instalar via [rustup.rs]https://rustup.rs
2. **Visual Studio Build Tools 2019 ou posterior** com o workload "Desenvolvimento para desktop com C++" — necessário para linkagem. Baixar de [visualstudio.microsoft.com]https://visualstudio.microsoft.com/visual-cpp-build-tools/
3. **Windows Terminal** ou **PowerShell 7+** (Windows Terminal recomendado para renderização UTF-8)
4. **Git for Windows** se instalar do código fonte

### Instalação Rápida (do código fonte — preferido)

```powershell
git clone https://github.com/danilo-aguiar-br/atomwrite.git
cd atomwrite
cargo install --path . --locked --force
```

### Instalação Rápida (do crates.io — quando 0.1.34 estiver publicada)

```powershell
# Abrir PowerShell 7+ ou Windows Terminal
rustup default stable
rustup target add x86_64-pc-windows-msvc

# Prefira pin de versão; o crates.io pode ainda listar versão mais antiga
cargo install atomwrite --locked --version "^0.1.34"

# Verificar (esperar saída NDJSON)
atomwrite --version
```

### Solução de Problemas

#### "error: linker 'link.exe' not found"

Instale Visual Studio Build Tools com o workload C++. O instalador está em
<https://visualstudio.microsoft.com/visual-cpp-build-tools/>. Após instalar,
reinicie o terminal para que o PATH atualizado seja carregado.

#### "error[E0433]: failed to resolve: use of undeclared type `AtomwriteError`"

Este bug foi corrigido em v0.1.4. v0.1.12 é um substituto drop-in que também inclui 6 novos subcomandos, G72 verificação de sintaxe real, G114 sidecar WAL, e 5 novos códigos de erro. Certifique-se de
instalar v0.1.12 ou posterior:

```powershell
cargo install atomwrite --locked --version "^0.1.12"
```

Se não puder atualizar, compile do código fonte com o fix aplicado.

#### "error: linking with `link.exe` failed: exit code: 1125"

Antivírus (Windows Defender, McAfee, etc.) está bloqueando o linker. Adicione
exceção para `%USERPROFILE%\.cargo` e `%USERPROFILE%\.rustup`, depois tente
novamente.

#### Mojibake na saída do console

Console legado do Windows (`cmd.exe`) não suporta UTF-8 por padrão. Use
**Windows Terminal** (que ativa UTF-8 automaticamente) ou execute:

```powershell
chcp 65001
```

antes de invocar atomwrite. A função `init_console` do atomwrite também ativa
UTF-8 e sequências ANSI nos handles do console Windows quando executada de
um terminal configurado adequadamente.

#### "operation not permitted" durante escrita atômica

O pipeline de escrita atômica tenta até 3 vezes em caso de `PermissionDenied`.
Se um arquivo está aberto por outro processo (ex.: editor sem liberação
adequada, scanner antivírus, busca indexada), as tentativas podem esgotar.
Feche o arquivo na aplicação que o segura e tente novamente.


## Instalando Versões Específicas

```bash
# Preferido: árvore fonte v0.1.34 (até publicar no crates.io)
cargo install --path . --locked --force

# Pin no crates.io quando 0.1.34 estiver publicada
cargo install atomwrite --locked --version "^0.1.34"

# Pin histórico de exemplo (0.1.28)
cargo install atomwrite --locked --version 0.1.28

# Forçar reinstalação (path ou versão pinada)
cargo install --path . --locked --force
```

A flag `--locked` garante que o `Cargo.lock` seja respeitado, garantindo um build
reproduzível que corresponde ao que os maintainers testaram.

Nota: o crates.io pode ainda listar versão mais antiga depois que a árvore chega em 0.1.34.
Use `cargo install --path . --locked --force` para a árvore que você tem no checkout.


## Verificando Instalação

```bash
atomwrite --version
# Esperar saída NDJSON com versão, data de build e info de plataforma
```

Se o comando não for encontrado, garanta que `~/.cargo/bin` (Linux/macOS)
ou `%USERPROFILE%\.cargo\bin` (Windows) está no seu `PATH`.


## Compilando do Código Fonte (todas plataformas)

```bash
git clone https://github.com/danilo-aguiar-br/atomwrite.git
cd atomwrite
cargo build --release
./target/release/atomwrite --version
```

O binário de release fica em `target/release/atomwrite` (ou `atomwrite.exe`
no Windows).


## Builds Slim vs Full por Features (v0.1.34)

A v0.1.34 expõe features do Cargo para trocar tamanho AST por um binário slim de agente.

| Perfil | Comando | Tamanho aprox. | Notas |
|---|---|---|---|
| slim (`core` apenas) | `cargo install --path . --locked --force --no-default-features --features core` | ~7.7 MiB | size-gate local ≤15 MiB |
| default (subconjunto AST) | `cargo install --path . --locked --force` | ~52 MB | `core` + `ast` + `lang-rust` + `lang-ts` + `lang-py` |
| `full` | `cargo install --path . --locked --force --features full` | ~52 MB+ | default + `lang-full` + `watch` + `semantic` |

### Flags de feature

- `core` — read/write/edit/search/replace atômicos e demais comandos sem AST
- `ast` — stack tree-sitter / ast-grep (`transform`, `scope`, `query`, `outline`, `--syntax-check`)
- `lang-rust` / `lang-ts` / `lang-py` / `lang-go` — packs de linguagem para AST
- `lang-full` — todos os packs de linguagem acima
- `watch` — subcomando `watch` (`notify`)
- `semantic` — helpers semânticos reservados a caminhos opcionais
- `full``default` + `lang-full` + `watch` + `semantic`

### Exemplos

```bash
# Instalação slim (agente)
cargo install --path . --locked --force --no-default-features --features core

# Instalação default/full com AST
cargo install --path . --locked --force

# Default mais watch e todas as linguagens
cargo install --path . --locked --force --features full

# Verificar instalação (41 subcomandos no --help)
atomwrite --version
atomwrite --help
```

O crates.io pode ainda publicar versão mais antiga até o maintainer lançar 0.1.34. Prefira
`--path . --force` para esta árvore.


## Verificação de Saúde (G119)

Após instalar v0.1.15 ou posterior, execute os comandos de saúde do WAL para confirmar que os novos subcomandos estão cabeados corretamente. Estas operações são read-only ou de reparo escopado, seguras para smoke tests locais pós-instalação.

### Inspecionar Estado do WAL (read-only)

```bash
atomwrite --workspace . wal-stats
```

Envelope NDJSON esperado (truncado):

```json
{"type":"result","journals_total":0,"journals_started":0,"journals_committed":0,"journals_aborted":0,"stale_threshold_secs":86400,"reclaimable":0,"action":"stats","elapsed_ms":3}
```

O campo `reclaimable` conta journals terminais (Committed ou Aborted) mais antigos que o threshold de obsolescência. Um valor não-zero indica sidecars órfãos elegíveis para limpeza segura.

### Reap de Journals Terminais

A camada G119 L3 adiciona `wal-heal` para remover journals terminais (Committed e Aborted). Nunca toca em entradas Started.

```bash
# Remover todos os journals terminais independentemente da idade (seguro: ignora Started)
atomwrite --workspace . wal-heal --threshold-secs 0
```

Use este comando em smoke tests pós-instalação, hooks de pre-build locais, ou após uma varredura de recuperação de crash.

## Validação Cross-Compile (para contribuidores)

O projeto inclui um gate de cross-compile para detectar erros de compilação
exclusivos de Windows antes do release. Execute:

```bash
# Instalar targets Windows
rustup target add x86_64-pc-windows-gnu
rustup target add x86_64-pc-windows-msvc

# No Linux, instalar mingw-w64 para o target GNU
sudo dnf install mingw64-gcc mingw64-gcc-c++  # Fedora
sudo apt install mingw-w64                     # Ubuntu

# Executar gate de cross-compile
cargo test --test cross_compile_check -- --ignored
```

Isto é obrigatório para qualquer release que toque em caminhos de código
`#[cfg(windows)]`, conforme o fix do GAP 14 em v0.1.4 (preservado para referência histórica; instale v0.1.12 ou posterior).


## v0.1.20 — Novidades

Esta release introduz uma nova camada de segurança chamada **intention guards** e renomeia a flag global `--lang` para `--locale` para desambiguar do seletor tree-sitter `--lang` usado por `scope` e `transform`.

### Intention Guards (5 flags OPT-IN)

- `--require-backup <N>` — recusa a operação quando menos de `N` backups retidos existem para o alvo
- `--confirm` — emite um prompt de confirmação listando a mutação planejada em NDJSON antes de executar
- `--auto-rotate <N>` — rotaciona automaticamente o anel de backups para `N` entradas após uma escrita bem-sucedida
- `--risk-threshold <LOW|MEDIUM|HIGH>` — bloqueia operações cujo risco classificado atinge ou excede o threshold
- `--locale <en|pt-BR>` — renomeado de `--lang` para desambiguar do `--lang` tree-sitter

### Outras Adições

- `count --by-size` — lista os maiores arquivos da árvore com tamanhos e contagem de linhas
- `read --mode raw|envelope` — seleciona entre saída byte-stream e envelope NDJSON estruturado
- `search --no-begin-end` — desabilita a decoração implícita de âncoras `^` e `$` na saída regex
- `write --preserve-timestamps` — preserva o mtime do arquivo fonte ao sobrescrever
- `scope --lang rust` — alias explícito aceito para simetria ergonômica com `transform --lang`

### Estatísticas

- 700+ testes listados (working tree v0.1.34)
- 11 GAP-2026 fechados
- 3 targets de cross-compile Windows verdes
- ADRs em `docs/decisions/` até 0051; 38 schemas JSON

### Migração `--lang` para `--locale`

```bash
# Descobrir todos os arquivos com --lang
rg -l -- '--lang\b' .

# Substituir em massa preservando outros matches
fd -e sh -e md -e toml -e yml -e yaml -e json -x sd -- '--lang\b' '--locale' {}

# Ou via ruplacer
ruplacer --subvert --lang --locale
```


## v0.1.21 — Novidades

Esta release fecha 3 GAP-2026 items e altera o comportamento padrão de retenção de backups:

- **`--allow-sequential-drift`** em `edit` — flag opt-in para pipelines de edição sequencial
- **`--backup` paridade 4/4**`edit` e `rollback` agora aceitam `--backup` (eram hardcoded `false`)
- **`--keep-backup`** em 6 sub-comandos — flag opt-in para preservar o backup após sucesso
- **Mudança de comportamento padrão** — backups são DELETADOS após operações `--backup` bem-sucedidas; adicione `--keep-backup` para preservar
- 555+ testes passando, 1 novo ADR (0038)

## v0.1.22 — Novidades

Esta release adiciona 2 novos sub-comandos para limpeza e padrão de N-edits-em-1-invocação:

- **`prune-backups [PATHS]...`** — limpeza manual de siblings `.bak.YYYYMMDD_HHMMSS` legados
  - Flags: `--max-age-secs <SECONDS>`, `--max-count <N>`, `--dry-run` (default true)
  - Saída NDJSON com linhas por backup e summary
- **`edit-loop <PATH>`** — aplica N pares `{old, new}` via NDJSON no stdin em 1 invocação
  - Flags: `--workspace`, `--expect-checksum`, `--partial`, `--fuzzy`, `--backup`, `--keep-backup`
  - Saída NDJSON com `pair_result` por par e summary
- 575+ testes passando, 2 novos ADRs (0039, 0040), 2 novos schemas NDJSON
- 32 sub-comandos totais (de 30 em v0.1.20)

### Instalar v0.1.22

```bash
# Do crates.io
cargo install atomwrite --locked --version "^0.1.22"

# Verificar
atomwrite --version

# Smoke test dos novos sub-comandos
atomwrite --workspace . prune-backups --max-age-secs 86400 .
printf '%s\n' '{"old":"foo","new":"bar"}' \
  | atomwrite --workspace . edit-loop src/foo.rs
```