Skip to content

Latest commit

 

History

History
103 lines (95 loc) · 24.5 KB

README.md

File metadata and controls

103 lines (95 loc) · 24.5 KB

ADRs (Architecture Decision Records) — Index

  • Historical (pre-0.1.35): product ATOMWRITE_* / env knobs described below are superseded. Runtime config is CLI flags + XDG config.toml / atomwrite config only.
  • Format: Michael Nygard's ADR template (Status, Context, Decision, Consequences, Alternatives, Trigger to revisit). The ADRs 0058 to 0074 also carry an Evidence section with file:line references.
  • Authoring rule: Every non-trivial change to atomwrite (a new subcommand, a new error variant, a new dependency) MUST be accompanied by an ADR or by an update to an existing ADR.
  • Storage: One file per ADR in docs/decisions/. Filename is NNNN-kebab-case-slug.md. Numbering is monotonic.
  • Mirrors: Every ADR has a pt-BR mirror named NNNN-kebab-case-slug.pt-BR.md next to the English file. The English file is canonical.
  • Immutability: An accepted ADR is not rewritten. A later ADR amends it, and the amendment is recorded in the Status of the amending ADR.

Index

ADR Decision EN pt-BR
0019 v0.1.12 chose tree-sitter-language-pack over direct tree-sitter deps to keep binary small. 0019 0019
0020 G114 WAL sidecar path is .atomwrite.journal.<basename>.atomwrite.journal.json. 0020 0020
0021 v0.1.12 query and outline accept only kind names, not tree-sitter S-expressions. 0021 0021
0022 G72 tree-sitter REAL syntax check replaces (not adds to) the bracket heuristic. 0022 0022
0023 G114 recovery is consultative (no auto-replay, no auto-delete). 0023 0023
0024 get/del TOML dotted path navigation is manual Table descent, not toml_edit::Table::get. 0024 0024
0025 query --positions is valid in --query/--tree, silently ignored in --kinds. 0025 0025
0026 Multi-pair --old/--new gains fuzzy parity, per-pair pair_results, failed_pair_index on error, and opt-in --partial. 0026 0026
0027 write resolves the target via validate_path before append/prepend, line-ending auto-detection, and --expect-checksum (fixes CWE-367 double path identity; checksum drift exits 82 with a divergent CWD). 0027 0027
0028 Five-layer autonomous WAL cleanup: L1 --wal-policy prevention, L2 Drop guard, L3 --no-auto-heal startup heal, L4 heuristics (TTL/LRU/rate/sentinel/archive), L5 wal-stats. 0028 0028
0029 L3 explicit cross-validation of --append/--expect-checksum/--allow-empty-stdin via tracing::info and --no-checksum-when-empty opt-out. 0029 0029
0030 replace pre-validates root paths against the jail, G120 L3 end-to-end test, G117 edge cases (Unicode, CRLF, multi-pair same --old). 0030 0030
0031 search and replace resolve root paths against the workspace through a shared helper (CWE-367). 0031 0031
0032 query accepts tree-sitter S-expressions through Query::new (the v0.1.12 docs promised it but the code never implemented it). 0032 0032
0033 7 exit-code drifts between the published docs and the binary (STATE_DRIFT, SYNTAX_ERROR_DETECTED, ORPHAN_JOURNAL, BROKEN_PIPE, binary read, ARGUMENT_PARSE_ERROR, missing --workspace). 0033 0033
0034 clap --help nunca declarado antes da implementação (5 dos 11 GAP-2026 tinham esse anti-pattern; motivação para help-driven testing). 0034 0034
0035 Seis camadas de defesa em profundidade (--require-backup, --confirm, --preview/--yes, --auto-rotate, --risk-threshold) + risk_assessment no envelope, motivadas pelo incident c24-framework34.html de 2026-06-15. 0035 0035
0036 Single-pair com zero matches retorna NO_MATCHES (exit 1); multi-pair aplica matched e relata unmatched em pair_results (exit 0). 0036 0036
0037 Rename GlobalArgs.lang flag --lang para --locale; env var ATOMWRITE_LANG e campo args.global.lang preservados; namespace --lang liberado para subcomandos (histórico, pré-0.1.35, superado). 0037 0037
0038 keep_backup default false + helper delete_backup_quietly; paridade de --backup em 4/4 subcomandos (write, edit, replace, rollback) e --keep-backup em 6/6 (write, edit, replace, rollback, apply, batch). 0038 0038
0039 Sub-comando para N pares em 1 invocação; re-captura checksum opcional. 0039 0039
0040 Cleanup manual para legados v0.1.20; flags --max-age-secs e --max-count. 0040 0040
0041 allow_hyphen_values for 12 CLI text-accepting fields across 8 structs, since the three positionals require --; prevents exit 2 cascade in agent pipelines. 0041 0041
0042 Backup default true in 9 content-mutating structs; --no-backup and ATOMWRITE_BACKUP=0 for opt-out (historical, pre-0.1.35, superseded). 0042 0042
0043 Blocking shrink guard (exit 65) when --expect-checksum is active and stdin shrinks >50%; --allow-shrink for override. 0043 0043
0044 --old-file/--new-file to bypass ARG_MAX; cross-mixing validation and trailing newline stripping. 0044 0044
0045 ARGUMENT_PARSE_ERROR (exit 2) gains context-aware suggestion field pointing to --old-file/--new-file when error involves hyphen values. 0045 0045
0046 diff now resolves file_a and file_b against workspace via validate_path (was the only command violating ADR-0027 convention). 0046 0046
0047 scope read-only mode now correctly reports files_matched via Node::find_all; files_modified=None when no action configured. 0047 0047
0048 Single BackupOpts struct flattened via #[command(flatten)] into 15 mutating subcommands; single resolve_backup() with precedence ATOMWRITE_BACKUP env > CLI flags > .atomwrite.toml [defaults] > built-in default (historical, pre-0.1.35, superseded). 0048 0048
0049 load_config called once in lib.rs::run(); DefaultsSection propagated to every mutating handler, closing GAP-CONFIG-DEFAULTS-DEAD. 0049 0049
0050 main.rs computes stdin.is_terminal() once and propagates stdin_is_tty down to cmd_edit; stdin-consuming edit modes fail fast with exit 65 instead of blocking indefinitely. 0050 0050
0051 v0.1.29: fecha P0–P3 e residuais: fuzzy compartilhado, best_candidate, features core/slim, recipe real, durability, renameat2, agent-surface, foundation P3, schemas e documentação EN/PT alinhados à 0.1.29. 0051 0051
0052 v0.1.30: fecha residual P17–P24: match_count, indent_adjusted, fuzzy off rejeitado, backup reflink_or_copy, recipe bak skip, sparse outline AST real, semantic-merge line-based, schema e docs. 0052 0052
0053 Documented Clap audit exceptions (v0.1.32): BackupOpts.backup: Option<bool> tri-state; prescan_json_schema via std::env::args before Clap. 0053 0053
0054 v0.1.34: one-pass fuzzy; embeds force 1; timeout default 120 / exit 124; cancel mid-cascade; caps; no telemetry; docs-complete of 0.1.33. Amended by 0065 and 0073. 0054 0054
0055 v0.1.36: closes/mitigates GAP-2026-019…033: content-source jail + scratch init, error ok:false + match_count, fuzzy honesty (null similarity / dual-gate / soft-floor), agent-native --select/--filter/--limit, extract --field, CANONICAL_SUBCOMMAND_COUNT=46, ADR surface. Amended by 0061, 0065 and 0072. 0055 0055
0056 Removes release_max_level_info so -vv/-vvv stay JSON-only with DEBUG/TRACE in release; measured median +1.60 % (inside noise), binary +17 216 bytes. 0056 0056
0057 Documents third-party environment reads (sys-locale, directories, ureq proxy), keeps tree-sitter-language-pack download (measured: outline/query fail without it), MSRV 1.89, rust-i18n 4.2, serde-saphyr, notify 8. 0057 0057
0058 v0.1.37: the 47th subcommand config path|list|get|set|unset over 37 typed keys, mandatory --scope, comment-preserving atomic write, answered before the config load. 0058 0058
0059 v0.1.37: one src/retry.rs with full jitter, two stop conditions, 15 ms cancel slices and a budget cut to the global deadline. 0059 0059
0060 v0.1.37: one 8 MiB byte budget shared by every search worker (search.max_inflight_bytes, 4 MiB to 1 GiB); default -j memory 142.6 MB to 45.3 MB. 0060 0060
0061 v0.1.37: NdjsonWriter::publish_failure and VerdictPublished, so a failed run ends in exactly one terminal event; files_failed and errors[]. 0061 0061
0062 v0.1.37: WAL H3 rate limit applies at journal creation only, startup_wal_heal limited to the argv directories with a 100 ms budget, cancelled runs leave no journal. 0062 0062
0063 v0.1.37: SIGPIPE has a cooperative handler with exit 141, a DELIBERATE DEVIATION from the literal SIG_DFL owner rule (measured: 7 to 11 locks and 3 to 7 journals left with SIG_DFL). 0063 0063
0064 v0.1.37: automatic threads min(CPUs, 16, RAM cap), walker capped at 12, explicit -j N honoured, rayon pool built on demand. 0064 0064
0065 v0.1.37: fuzzy.max_content_bytes ceiling (256 MiB), escape_normalized cut at 32 MiB, CancelPoll in every fuzzy loop, dual-gate ties only. 0065 0065
0066 v0.1.37: DoctorChecksFailed, doctor --strict exits 1 with DOCTOR_CHECKS_FAILED and the report as the single terminal line. 0066 0066
0067 v0.1.37: closed terminal schemas, diff as a oneOf of four branches, 55 names served by --print-schema. 0067 0067
0068 v0.1.37: common::hermetic for tests plus two source guards (hardcode; let _ = and panics) with empty allowance lists. 0068 0068
0069 v0.1.37: constants.rs split into three include! parts and large modules split into .inc.rs files, public paths unchanged. 0069 0069
0070 v0.1.37: watch is an opt-in feature; the default binary answers exit 78 with a rebuild hint and agent-surface reports available: false. 0070 0070
0071 v0.1.37: extract-artifact returns bounded signal from PDF, OOXML and image headers, never raw bytes; limits are extract.* config keys. 0071 0071
0072 v0.1.37: agent-native surface with global stream shaping flags, --print-schema answered before clap, --non-interactive and --confirm-side-effect. 0072 0072
0073 v0.1.37: one terminal cancel point in the dispatch, deadline_exceeded always serialized, exits 129, 130, 143 and 124. Amends 0054. 0073 0073
0074 v0.1.37: read-modify-write verbs take the advisory lock before they read (acquire_for_update), atomic_write_based fails with STATE_DRIFT (exit 82) on a stale base, and apply is strict (MATCH_FAILED, nothing written). 0074 0074
0075 v0.1.37: tree-sitter-language-pack 1.22.1, ast-grep 0.51 and tree-sitter 0.27 in one move, which takes zstd from 0.13.3 to 0.14.3 and clears 4 vulnerabilities and 10 unsound warnings; rust-version rises to 1.90. Amends 0019 on the pack and 0057 on the MSRV. 0075 0075
0076 v0.1.37: read takes several operands and expands one level of *, ? or [ itself, so --format raw concatenates like cat; the byte channel never carries an error envelope; --sort summaries stop claiming walker_stopped_early. 0076 0076
0077 v0.1.37: a match is a file that answered (scope), a failure counts once per distinct path (transform --rules), a broken ignore file is a reported failure, case joins the answer-keeping family, the five read verbs carry the target stamp, and files_skipped/files_visited/total_matches descriptions match their producers. 0077 0077
0078 v0.1.37: one schema per verb describing the whole stream, the error envelope as a branch of every union, child tags declared, and the served list down from 59 to 55 names backed by 54 files. Supersedes the name list of 0067. 0078 0078
0079 v0.1.38: the exclusive lock is taken on the target inode with try_lock, the sidecar becomes best-effort compatibility, the swap revalidates the inode with same_file and fails STATE_DRIFT (exit 82), a read-only directory selects the in-place strategy, and apply/set/del/edit pass the base digest. Supersedes the sidecar requirement of 0031. 0079 0079
0080 v0.1.38: sparse outline stops dropping the atomwrite journal by name, so the dotfile rule is the only exclusion and --hidden counts it; files_scanned becomes 3 on a folder the other verbs already counted as 3. Amends the walk policy of 0077. 0080 0080
0081 v0.1.38: write publishes write_strategy, apply publishes write_strategy and backup_skipped, and a lock that cannot be taken names the target instead of the .atomwrite.lock sidecar. Amends 0078. 0081 0081
0082 v0.1.38: sparse list honors --hidden, both sparse listing verbs drop a timestamped backup copy, and files_scanned says when a dotfile counts. Amends 0077 and refines the measurement of 0080. 0082 0082
0083 v0.1.38: hash, copy -r and semantic-search hide dotfiles by default, WholeTree becomes CopyTree, sparse list and sparse outline take --all, and a path named in the invocation still wins. Amends 0082 and completes 0077. 0083 0083
0084 v0.1.38: the seven mutating verbs publish write_strategy and backup_skipped, delete and the read actions of config report the mechanism honestly, and batch publishes the verdict per operation. Extends 0081. 0084 0084
0085 v0.1.38: the nine verbs that rewrite content publish the same verdict, a preview publishes none, del on an absent key omits the field, and batch delete refuses to copy a copy. Extends 0084. 0085 0085
0086 v0.1.38: apply publishes backup_path, a failed run that restored files publishes one rollback record, a failed restoration exits as TRANSACTION_ROLLBACK_FAILED, the schema of the verb becomes a union of plan, applied and rollback, and every optional verdict field declares a plain string. Extends 0081 and 0085. 0086 0086
0087 v0.1.38: the snapshot of batch --transaction is removed when the run ends unless --keep-backup keeps it, --no-backup wins over it, and the rollback record of apply and of batch names every reverted path in target_resolved. Extends 0086. 0087 0087
0088 v0.1.38: the commit keeps the snapshot of a target the transaction deleted, a failed reversal publishes failed_paths and backups_preserved, apply stamps stdin when the patch names its own file, and the rollback record publishes target_resolved always as an array. Extends 0087. 0088 0088
0089 v0.1.38: target_resolved is always an array and the schema declares one shape, batch publishes warnings and backup_path on each operation and backups_preserved on the summary, move and copy keep the snapshot of the destination they overwrite, and a failed apply publishes the copies its rollback left. Amends 0088, amended by 0090. 0089 0089
0090 v0.1.38: a transactional delete or move reports the snapshot the transaction already made instead of writing a second copy, and a failed apply carries the copy it created on the error and publishes it in backups_preserved. Amends 0089. 0090 0090
0091 v0.1.38: a transactional write, replace, edit or copy reuses the snapshot the transaction already made, --keep-backup leaves one copy instead of two, the commit names a rewrite it preserves, and the source of move and copy is no longer snapshotted. Amends 0088 and 0090. 0091 0091
0092 v0.1.38: delete creates a copy only when the call asks, --keep-backup only preserves one that exists, and the batch delete follows the same rule. Clarifies 0038, amended by 0093. 0092 0092
0093 v0.1.38: [defaults].backup becomes Option<bool>, so an absent key keeps each verb's default while a written true reaches delete and the batch; --no-backup still wins and config get still omits value while the key is not written. Amends 0092. 0093 0093
0094 v0.1.38: delete --recursive owns the whole named tree, removes hidden, ignored, linked, fifo, socket and device entries, refuses a backup inside the tree, and reports a surviving directory with the measured I/O error instead of a synthetic exit 65. Amends 0083, 0092 and 0093. 0094 0094
0095 v0.1.38: search renders submatch text from the matched bytes with from_utf8_lossy instead of slicing &str at a matcher offset, so a zero-width or byte-oriented match inside a multi-byte character no longer aborts the run. 0095 0095

ADRs of the 0.1.35 series (docs/adr)

  • These three ADRs live in docs/adr/ with the name ADR-0.1.35-*.md, outside the NNNN-slug.md convention, and are indexed here so no ADR is left without a link.
  • They keep their original shape without the template's Alternatives and Trigger to revisit sections, because an accepted ADR is not rewritten, and this line declares the exception.
ADR Decision EN pt-BR
ADR-0.1.35-g035-env-detect-allowlist G-035: OS environment probe allowlist for env_detect. Superseded in 0.1.37: no environment variable is read and env_detect uses file probes only. EN pt-BR
ADR-0.1.35-p3-fuzzy-reject Rejects the P3 fuzzy AVALIAR items (nucleo Smith-Waterman, phonetic, BM25, remote embeddings, OS multi-process fan-out) for v0.1.35 and keeps the local cascade. EN pt-BR
ADR-0.1.35-simd-memchr SIMD fuzzy locate: keeps memchr and strsim and rejects triple_accel as a default dependency for v0.1.35. EN pt-BR