ADR 0002: Architecture for Accepting diff / sortdiff in ayame-editor¶
- Status: Accepted (2026-07-10)
- Related Issue: hjosugi/ayame-diff#4
- Implementation Issues: hjosugi/ayame-diff#5 #6 #7 #8 #9
- Origin Epic: hjosugi/ayame-editor#104
Background¶
The diff-related features from ayame-editor (Rust) will be migrated to this project (Go, zero dependencies policy). Targeted reference implementation:
crates/ayame-cli/src/diff.rs(line 610)cmd_diff: bounded resync window line diff. Does not hold the full line LCS matrix, but scans only the previouswindowlines from anchor lines to resynchronize, making it O(n) and memory-bounded, suitable for large files. Output options include unified (default),--side-by-side,--json,--summary. Controlled via--max-hunks,--max-lines,--window,--width.cmd_sortdiff: External sorts both files into temporary UTF-8 files, then passes them todiff_documents. Supports--key/-k,--delim/-t,--quote,--numeric/-n,--reverse/-r,--csv,--budget,--spill-dir.- Data model:
DiffResult/DiffHunk/DiffKind{Insert,Delete,Replace}. serve/ops.rs:968-1134(/api/diff),web/src/search.ts:539-741(diff view) → To be received on the GUI side (#10 #11).
Decisions¶
1. Migration approach: Re-implementation in Go¶
No Rust→Go FFI or subprocess linkage; pure re-implementation in Go.
Aligns with the zero-dependency (standard library only) policy, maintaining single binary distribution, go install, and ease of cross-compilation.
Will directly follow the reference implementation's algorithm (bounded resync window) and data model (Hunks of Insert/Delete/Replace).
2. CLI interface: Subcommand-based (with backward compatibility)¶
ayame-diff csv [flags] --left A --right B # Existing: CSV/TSV key comparison
ayame-diff text [flags] LEFT RIGHT # New (#5): line diff (resync window)
ayame-diff sorted [flags] LEFT RIGHT # New (#7): external sort + text diff
ayame-diff [flags] # Default = CSV compatibility (backward compatible)
Note (2026-07-10): Interactive TUI wizard (#25) has been removed. Current default/no-argument invocation shows usage and exits. The
#5subcommand will assign the default/no-argument case to CSV.
Safe defaults + advanced escape hatch (Sindre Sorhus style):
- Existing users'
ayame-diff --left ... --right ...will dispatch to default = csv after subcommand implementation. - New features will be placed under explicit subcommands, avoiding mixing unrelated flags (no
--modeflag approach). Reason: different modes have different valid flags; separating via subcommands makes help and validation clearer. - Default output is unified (human-readable). Use
--jsononly when machine-readable output is needed.
Implementation of the subcommand dispatcher will be done in #5 (only the approach is fixed in this ADR).
Future serve (#10) / gui (#14) can naturally add their own subcommands under the same first argument.
3. Scope of shared engine (small, focused components)¶
Following the component division principle (Sindre Sorhus: Small Focused Modules), avoid creating a monolithic class; define clear boundaries.
Base on existing internal/engine (external sort/partition foundation):
| Package (planned) | Responsibility | Origin |
|---|---|---|
internal/engine (existing = fcsv) |
CSV/TSV parsing, key comparison, external sort/partition | Current implementation |
internal/linediff (new #5) |
line diff with bounded resync window, Hunk{Insert/Delete/Replace} |
Port from diff.rs |
internal/diffout (new #6) |
formatting unified/side-by-side/JSON/summary (separated from linediff) | Port from diff.rs |
internal/worddiff (new #8) |
word-level LCS highlighting within Replace hunks | Port from search.ts |
sortedwill not perform external sort itself. It reuses the existinginternal/enginesort/spill infrastructure, passing output tolinediff(similar tocmd_sortdiff). Job control (parallelism, backpressure, cancellation) will also share existing engine mechanisms.linediffwill separate I/O and algorithm, keeping a pure core that does not depend on output formatting (diffout) (for testability and GUI reuse).
4. Encoding support¶
The reference implementation supports UTF-8 / Shift_JIS / EUC-JP / UTF-16, but this will be separated into #9. Initial port (#5-#8) will assume UTF-8, with non-UTF-8 handling deferred to #9.
5. Zero dependency policy¶
Maintain. Only standard library. Exceptions are allowed under clearly documented criteria:
- Only in areas where standard library does not exist and custom implementation is practical (e.g., non-UTF-8 decoding =
golang.org/x/text/encodingwill be reconsidered in #9, or for GUI WebView, etc.). - When exceptions are made, record "why not possible with standard library" in the relevant Issue, and update
THIRD_PARTY_NOTICES.md. - The core CLI (
csv/text/sorted) will strictly maintain zero dependencies.
Completion criteria (what this ADR will fulfill)¶
Once the migration approach (Go re-implementation), CLI design (subcommands + backward compatibility), and shared engine scope (reuse of linediff, diffout, worddiff) are fixed, and implementation issues (#5 line diff, #6 output, #7 sortdiff, #8 word diff, #9 encoding) are ready to start, the work can proceed.
Rejected proposals¶
--mode=csv|text|sortedflag approach: Rejected because different modes have different valid flag sets, complicating help and validation (subcommands will separate namespace).- Including Rust binaries / calling subprocesses: Rejected because it would lose the benefits of single binary distribution, zero dependencies, and cross-compilation.