fix: URL opener and +show-face output match Ghostty, register fixes

Resolves the parity items of docs/rewrite/notes/review-rv15-codex.md
(final-Z18.md):
- os::open inherits stdin like Zig's Child.init, strips LD_LIBRARY_PATH
  only in Snap builds (new `snap` cargo feature, off by default, like
  Zig's snap build option) and bounds output collection to 50 KiB per
  stream (StdoutStreamTooLong/StderrStreamTooLong).
- +show-face writes diagnostics and lookup lines in the exact fragments
  Zig's formatter produces, so buffer drains happen at the same byte
  positions (0 diffs vs /usr/bin/ghostty over 0-44 bad options for
  three codepoints); its tests no longer parse the test runner's argv.
- DEVIANT_FIXES.md: five entries reworded and four removed that were no
  longer deviations (verified against code and oracle).

Test Plan:
- cargo test -p ghostty-os open; cargo test -p ghostty-cli show_face
This commit is contained in:
ddidderr committed 2026-10-12 15:37:24 +02:00
1 parent 0dffc62bdf
commit 465a85b6d5
6 files changed
+296 -53

No files matched your search

+5 -9
View File
@@ -55,7 +55,7 @@ when this file was written.
| 27 | Build data: webgen output | `build/webgen/main_actions.zig:5-6`, `main_commands.zig:6`, `main_config.zig:6` | A 2048-byte stdout buffer that is never flushed, so the generated website files are truncated. | The complete files are emitted. | e4cdd8e | none (checked byte-identical to Zig output of a patched copy, per `final-Z4.md`) |
| 28 | CLI: `+list-colors` plain output | `cli/list_colors.zig:59-72` | 4096-byte buffer, never flushed; piped output stops midway through `PeachPuff3` (12,297 bytes). | Flushed (15,434 bytes). | 6286e02 | none; found by RV11 (`review-rv11-codex.md`) |
| 29 | CLI: `+list-themes` diagnostics | `cli/list_themes.zig:124-131,171` | The messages ("Could not find the Ghostty resources directory", "No themes found...") go to a 4096-byte stderr buffer that is never flushed, so they are lost. | Flushed when the action ends. | `410d8fc` fix-deviant(cli) | `zig_writer::tests::unflushed_buffer_is_flushed_on_drop` |
| 30 | CLI: stdout as a regular file | `std.fs.File.writer` (Zig 0.15.2) as used in `cli/show_face.zig:68-73`, `cli/help.zig:34`, `cli/validate_config.zig:43-46`, `cli/show_config.zig:84` | The writer `pwrite`s at its own offset starting at 0: with stdout redirected to a file, output overwrites itself and earlier file content, and `Writer.end` truncates. | Always appends at the current end; no truncation. | `410d8fc` fix-deviant(cli) (append behaviour first in `f76179f`) | `zig_writer::tests::regular_file_output_is_complete_and_appended` |
| 30 | CLI: stdout as a regular file | `std.fs.File.writer` (Zig 0.15.2) as used in `cli/show_face.zig:68-73`, `cli/help.zig:34`, `cli/validate_config.zig:43-46`, `cli/show_config.zig:84` | The writer `pwrite`s at its own offset starting at 0: with stdout redirected to a file, output overwrites itself and earlier file content, and `Writer.end` truncates. | Writes sequentially at the inherited descriptor's current offset (no `pwrite` from offset 0, so earlier content and the writers' own output are not overwritten; this appends only when the descriptor is opened for append, e.g. `>>`); no truncation. | `410d8fc` fix-deviant(cli) (append behaviour first in `f76179f`) | `zig_writer::tests::regular_file_output_is_complete_and_appended` |
## Upstream quirks deliberately kept (not fixed)
@@ -81,22 +81,18 @@ Only entries with an observable behavioural difference are listed.
| Area | Zig/Ghostty behaviour | Rust behaviour | Where | Commit |
|------|-----------------------|----------------|-------|--------|
| Swift macOS app | Ships `macos/` | Not ported; the Rust side provides the `libghostty` C API, Metal/CoreText code, XCFramework script. Only compile-checked (`just check-macos`), never run (no macOS here). | `ARCHITECTURE.md` (Out of scope), `notes/macos-M1*.md`, `final-Z4.md` | bab49ee, 75bf604, 231ee35 |
| Windows and wasm | Native targets | Compile-checked only (`just check-windows`, `just check-wasm`); not run. | `notes/windows-WIN.md`, `notes/wasm-W1.md` | 76771be, d89691b |
| Windows (and wasm natively) | Native targets | Windows is compile-checked only (`just check-windows`), never run. wasm is built and its Node smoke/ABI tests run (`just check-wasm`, `scripts/wasm-check.sh`), but not in a real browser. | `notes/windows-WIN.md`, `notes/wasm-W1.md` | 76771be, d89691b |
| Crash reporting | Sentry with Breakpad on macOS, `SIGSEGV` handlers, local DB/cache, sessions, init thread | In-process reporter: `.ghosttycrash` envelopes in `$XDG_STATE_HOME/ghostty/crash`, panic hook and signal handler, minidumps on macOS/Windows. No Sentry DB/cache dir, no sessions, no init thread; reports are written on any panic; the crash dir is resolved at init; the signal path writes no attachment. | `notes/crash-CR.md`, `ARCHITECTURE.md` (Scope changes) | b3145ad, 72bfac1 |
| Surface copy-on-select on release | `setSelection` returns early when the new selection equals the old one | Left-release copies directly via `copy_on_select`, because the early return would never copy | `notes/ghostty-core.md` | ad76ae2 |
| Locking / threading | Renderer mutex held while sending mailbox messages and running mouse reports (`.locked` sends); `process_links` called unlocked | Reports, IO messages and runtime actions are collected and run after the lock is released; `process_links` takes the lock itself; termio overflow goes to an ordered outbox | `notes/ghostty-core.md`, `notes/ghostty-termio-IO*.md` | 6629fb0, ad76ae2 |
| Invalid preedit text | Returns an error | Decoded lossily (U+FFFD) for renderer codepoints; no panic | `final-Z10.md` | db95444 (unverified) |
| Rendering of overlay / images | z2d overlay, wuffs image decoding, glslang+SPIR-V+spirv-cross | Direct RGBA overlay with approximate hairline placement; `png`/`jpeg-decoder`; `naga` GLSL front end (narrower than glslang, with a sampler2D helper rewrite) | `notes/ghostty-renderer-R1.md`, `R2.md`, `gaps-X2.md`; `just visual-parity` reports 0 differing pixels for the tested scenes | 568ce78, 871c301, f68b11d |
| Oniguruma | Native regex library for links and tmux | Hand-written matchers for the tmux parser; link regexes use the minimal `ghostty-onig` FFI crate | `notes/ghostty-vt-W2.md` | b2b248e, 2aa2a12 |
| zlib / PNG / base64 / shm | zig std, wuffs, simdutf, mmap | `flate2`, `png`, `base64` crate (ASCII whitespace ignored), `rustix` shm reads without mmap | `notes/ghostty-terminal-kitty.md`, `notes/ghostty-vt-W2.md` | d47408f, b2b248e |
| VT parser buffer | Fixed 2048-byte buffer with a reserved NUL | Growing `Vec<u8>` with a cap; differs only at exactly 2048 payload bytes for osc9/iterm2/text_sizing | `notes/ghostty-vt-W1.md` | b2b248e |
| VT parser buffer | Fixed 2048-byte buffer with a reserved NUL | Growing `Vec<u8>` with a cap that models the reserved-NUL capacity; no observable difference is known (internal representation only) | `notes/ghostty-vt-W1.md` | b2b248e |
| CSI W logging | Logs a spurious "invalid cursor tabulation control" after `CSI 2 W` / `CSI 5 W` | No log line (log-only) | `notes/ghostty-vt-stream.md` | 47b479d |
| Searching | `CircBuf` + overlap buffer, libxev thread | `VecDeque`, `crossbeam-channel`, 24 ms refresh timer; identical results, assertions about buffer layout dropped | `notes/ghostty-terminal-search-tmux.md` | 8e9be42 |
| Config strings | UTF-8 not required in many places | Escaped-bytes representation (`EncodedOs`) so non-UTF-8 survives; behaviour matched to Zig error names, but some filesystem diagnostics still print Rust OS error text (for example `theme=/etc/passwd/x`) | `notes/review-rv11-codex.md` (item 3; later status: unverified) | 672e8a4, 4bbe0d7 |
| `initial_input` escaping | `std.zig.stringEscape` (`\xNN`) | Non-ASCII code points use `\u{..}` because the config `Raw` value is a `String` | `notes/libghostty-L1.md` | 75bf604 |
| `+version` / build info | Real build metadata | Placeholder `build_info` values in places; `Rust version` row empty; `gtk-opengl-debug` follows `cfg!(debug_assertions)` (the `release` profile has them on, `production` off) | `notes/ghostty-cli.md`, `notes/ghostty-config.md` | 6286e02 |
| `codepoint-width --mode=wcwidth` (bench) | Calls libc `wcwidth` | Warn and no-op (libc FFI is forbidden); `simd` mode uses the same tables | `notes/perf-P1.md`, `notes/compat-GC-bench.md` | 0c4f0ee |
| D-Bus new-window arguments | Plain strings | Internal escape encoding; a literal U+FDD0 followed by a character can decode differently | `notes/review-rv8-codex.md` item 9 (status: unverified) | 1a13e8b |
| Config strings | UTF-8 not required in many places | Escaped-bytes representation (`EncodedOs`) so non-UTF-8 survives; behaviour and error names matched to Zig (for example `theme=/etc/passwd/x` gives `error.NotDir`, checked against the oracle) | `notes/review-rv11-codex.md` (item 3) | 672e8a4, 4bbe0d7 |
| `+version` / build info | Real build metadata | Placeholder `build_info` values in places; `gtk-opengl-debug` follows `cfg!(debug_assertions)` (the `release` profile has them on, `production` off) | `notes/ghostty-cli.md`, `notes/ghostty-config.md` | 6286e02 |
| OSC 52 base64 acceptance | Surface.zig:2149,2163 rules | Was different in both directions (Codex core audit); fixed to match Zig | `notes/review-core-codex.md` | 2f58f02 |
## Maintenance
+13
View File
@@ -0,0 +1,13 @@
# Z18 notes
## A. Deviant fix (separable)
- `crates/ghostty-apprt-gtk/src/ipc/new_window.rs`: `arguments_variant` now validates (UTF-8, no NUL) and returns `Error::IpcFailed` with a stderr message instead of `process::abort()` (Zig `new_window.zig:49-53`). Validation runs before connecting to the bus. Test `invalid_dbus_strings_are_rejected_without_abort` replaces the SIGABRT subprocess test.
- `docs/rewrite/DEVIANT_FIXES.md`: row 31.
## B. Parity
1. `crates/ghostty-cli/src/show_face.rs`: `write_diagnostic` / `write_lookup` write Zig's exact fragments (literal, `cli:`, digits, `:`, key, `: `, message, `\n`; hex padding separate from digits). Oracle (pipe) check: n = 0..44 copies of `--font-size=bad` x cp {65, 7, 0x1F600}: 0 diffs (includes the 23x case). Tests: `diagnostics_drain_at_zig_fragment_boundaries`, `lookup_line_pads_hex_and_drains_per_fragment`.
2. `crates/ghostty-os/src/open.rs`: stdin inherited; `LD_LIBRARY_PATH` removed only with the new `snap` cargo feature (default off; forwarded by root `Cargo.toml` `snap`); stdout/stderr bounded to 50 KiB each (overflow = error, like `collectOutput`; child is still reaped, unlike Zig). Tests: `opener_inherits_stdin`, `snap_env_is_stripped_only_for_snap_builds`, `output_collection_is_bounded_per_stream`.
3. `show_face.rs`: `run_args` takes a config loader; tests use explicit args (`test_config`), `run` uses `Config::load`.
## C. DEVIANT_FIXES.md corrections
Row 30 (offset wording) and the wasm, VT parser buffer, config strings, `+version` rows reworded; removed: invalid preedit, `initial_input` escaping, `wcwidth` bench, D-Bus escape encoding (no longer deviations).