Sync with upstream ghostty (1,150 commits)#22
Conversation
The README hasn't been updated in years basically! This updates the README to make libghostty a first class citizen of the project and to update our roadmap and goals for the project to more accurately reflect our current state and future plans.
The README hasn't been updated in years basically! This updates the README to make libghostty a first class citizen of the project and to update our roadmap and goals for the project to more accurately reflect our current state and future plans. I notably updated our roadmap to be more accurate to our state, e.g. we're stable now. I removed Windows because it's not a short term focus and I think libghostty is more important and enables that ecosystem a lot more (libghostty itself being already compatible with Windows). I also expanded on "fancy features" and clarified its to make Ghostty-specific sequences.
- Token is formatted without allocation - Reusable function for formatToken - Tests in portal.zig are actuall included now
Triggered by [comment](ghostty-org#11754 (comment)) from @mitchellh. Vouch: @tdgroot Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Triggered by [comment](ghostty-org#11771 (comment)) from @jcollie. Vouch: @deblasis Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Triggered by [comment](ghostty-org#11768 (comment)) from @jcollie. Vouch: @lynicis Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This is a continuation of the solid work done by @jcollie in PR ghostty-org#7864. I checked with him if I could take over to continue the implementation. His changes of last year have been adapted to be compatible with the current GTK implementation. Aside from just "making it work", I also dived into the portals and OpenURI implementation and made some improvements there. Notable improvements were: - Improved lifecycle management of glib resources in the OpenURI implementation - More forgiving error handling in OpenURI implementation by adding more fallbacks - Fixed some memory leaks - Less memory allocations in Portals implementation - Added tests for building the Portals request path Fixes ghostty-org#5991
A static libghostty-vt is also useful for wasm targets, as that allows linking with an application into a larger wasm module. See ghostty-org#11729 (comment)
Previously WindowPaddingBalance was defined inside Config.zig, which meant tests for renderer sizing had to pull in the full config dependency. Move the enum into renderer/size.zig as PaddingBalance and re-export it from Config so the public API is unchanged. This lets size.zig tests run without depending on Config.
The inline else switch in each C API getter expands the .invalid case, which has OutType void. When called with .invalid and a null out pointer, the @ptrCast(@aligncast(out)) panics before getTyped can return early. Handle .invalid explicitly in the outer switch of every getter to short-circuit before the pointer cast. This affects build_info, cell, row, terminal, osc, and render (three getters).
Add a new CI job that runs `zig build test-lib-vt` to test the lib-vt build step. The job mirrors the existing test job structure with the same nix/cachix setup and skip conditions. It is also added to the required checks list.
The colors_get function used structSizedFieldFits to guard the palette copy, which required the entire palette array to fit in the provided size. This prevented partial palette writes when the caller passed a truncated sized struct, since the guard failed even though the inner code already handled partial copies correctly. Remove the outer guard so the existing partial-copy logic applies. The setopt_from_terminal test expected alt_esc_prefix to be false on a fresh terminal, but the mode definition in modes.zig sets its default to true. Update the test expectation to match.
- Our `checkGhosttyH` calls need to be guarded on building Ghostty app which has it - Move FileFormatter to its own file to avoid poisoning test refs with Config.zig which pulls in the world - Move WindowPaddingBalance to renderer to avoid pulling in Config.zig - Add a `zig build test-lib-vt` CI job
Rename build-windows to build-libghostty-vt-windows to reflect that it only builds and tests libghostty-vt for now, and move it next to the other build-libghostty-vt jobs. Replace the manual PowerShell zig download/install with mlugg/setup-zig, which auto-detects the version from build.zig.zon and handles caching. Upgrade the runner from windows-2022 to windows-2025. Remove the generated-script-to-swallow-errors pattern in favor of direct zig build commands.
Extract the platform-specific page backing memory allocation into AllocPosix and AllocWindows structs behind a PageAlloc comptime switch. Previously, POSIX mmap calls were inlined at each call site. This adds a Windows VirtualAlloc implementation and routes all allocation through PageAlloc.alloc/free, making the backing memory strategy consistent and easier to extend.
The X11 color map parser in x11_color.zig uses @embedfile to load rgb.txt at comptime, then splits on \n. On Windows, git may check out rgb.txt with CRLF line endings, leaving a trailing \r on each line. This caused color names to be stored as e.g. "white\r" instead of "white", so all X11 color lookups failed at runtime. Strip trailing \r from each line before parsing. Also mark rgb.txt as -text in .gitattributes to prevent line ending conversion in future checkouts.
…y-vt (ghostty-org#11781) Our Windows build has been broken for a _long_ time. It hasn't actually worked and our CI was falsely passing when it was actually failing to build/test. This PR fixes that and fixes the issues it found so `libghostty-vt` can build and pass tests. **This is only for libghostty!** I'd still like to expand our _test_ coverage to all of Ghostty for Windows but libghostty is more important for that platform in the short term and it's an incremental piece of work. A couple windows compatibility issues fixed: - `terminal.Page` uses `VirtualAlloc` on Windows (thanks @deblasis) - Our rgb.txt loading was not resilient to CRLF endings
On Windows, shared libraries (DLLs) require an import library (.lib) for linking, and the DLL itself is placed in bin/ rather than lib/ by the Zig build. The CMake wrapper was missing IMPORTED_IMPLIB on the shared imported target, causing link failures, and assumed the shared library was always in lib/. Add GHOSTTY_VT_IMPLIB for the import library name, set IMPORTED_IMPLIB on the ghostty-vt target, and fix the shared library path to use bin/ on Windows. Install the DLL and PDB to bin/ and the import library to lib/ following standard Windows conventions. Apply the same fixes to ghostty-vt-config.cmake.in for the find_package path.
Use writerStreaming() instead of writer() for stdout in helpgen and main_build_data. The positional writer calls setEndPos/ftruncate in end(), which fails on Windows when stdout is redirected via captureStdOut() because ftruncate maps INVALID_PARAMETER to FileTooBig. Streaming mode skips truncation entirely since stdout is inherently a sequential stream. Replace scandir with opendir/readdir plus qsort in framegen since scandir is a POSIX extension not available on Windows.
Add a "Run Example" step to the build-examples-cmake-windows job so that each CMake example is executed after it is built, verifying the resulting binaries actually work. The executable name is derived from the matrix directory name by replacing hyphens with underscores, matching the project convention.
This reverts commit 7045114.
Triggered by [comment](ghostty-org#11999 (comment)) from @jcollie. Vouch: @BarutSRB Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Apple's recent libtool can warn about misaligned 64-bit archive members and silently drop them when merging static libraries. In Ghostty this showed up in the Darwin libtool step that builds libghostty-fat.a. Normalize each input archive by copying it and running ranlib on the copy before handing it to libtool. That rewrites the archive into a layout Apple's linker tools accept without flattening members through the filesystem or changing Ghostty's archive format.
…org#11999) ## Root cause Zig 0.15.2 can produce macOS `.a` archives where some 64-bit Mach-O members are only 4-byte aligned inside the archive. Recent Apple `libtool -static` does not handle that layout correctly: it emits `not 8-byte aligned` warnings and, in the failing case, silently drops those members when creating the combined static library. In Ghostty, this happened in the Darwin `libtool` merge step that builds `libghostty-fat.a`. The x86_64 input `libghostty.a` still contained the expected `libghostty_zcu.o` and about 97 exported `_ghostty_` symbols, but after `libtool -static` the output archive contained only 4 SIMD symbols because `libghostty_zcu.o` had been discarded. The same warning pattern also appeared in third-party input archives such as `libfreetype.a` and `libz.a`, so this was not only a `libghostty.a` problem. ## What needed to be done The inputs to Apple `libtool` needed to be normalized before they were merged. The safest fix is to copy each input archive and run `ranlib -D` on the copy before passing it to `libtool`. `ranlib` rewrites the archive into a form that Apple’s linker tools accept, fixing the alignment/layout issue without changing the archive’s semantic contents. ## Why this approach An `ar x` -> `ar rcs` workaround can also make the warnings go away, but it is a broader and riskier transformation. Extracting archive members into a flat directory is not semantics-preserving: - duplicate member basenames can collide - non-`.o` members can be lost - member order can change That means an `ar`-based rearchive can silently change valid archives while fixing alignment. `ranlib -D` avoids those hazards because it rewrites the archive in place instead of flattening it through the filesystem. `-D` is also important because plain `ranlib` is not deterministic. In local testing, `ranlib -D` still fixed the alignment issue, preserved all 97 `_ghostty_` symbols, produced no `libtool` warnings, and was byte-stable across repeated runs. ## Validation This was reproduced directly: - before normalization, running `libtool -static` on the affected x86_64 `libghostty.a` produced a `libghostty_zcu.o not 8-byte aligned` warning and the output archive dropped from 97 `_ghostty_` symbols to 4 - after `ranlib -D`, the same `libtool -static` command preserved all 97 `_ghostty_` symbols and emitted no alignment warnings After applying the normalization step, a clean `zig build` succeeded, and the final macOS xcframework archive contained 97 `_ghostty_` symbols in both the `x86_64` and `arm64` slices. ## Summary This was not a Metal issue, not an Xcode project issue, and not a stale-cache issue. The actual root cause was an Apple `libtool` interoperability problem with Zig-produced macOS archives. The required fix was to normalize each archive before the Darwin `libtool` merge step, and `ranlib -D` is the least invasive way to do that while preserving archive semantics.
When changeConditionalState returns null (no theme-conditional config rules), the Termio DerivedConfig inherits conditional_state from the app-level config which defaults to .light and is never updated. This caused colorSchemeReportLocked to always report light mode. Fix: override conditional_state with the surface's own config_conditional_state after creating the Termio DerivedConfig.
* Add cmux theme picker helper hooks * Fix cmux theme picker preview writes * Improve cmux theme picker footer contrast * Respect system theme in cmux picker * Skip theme detection in cmux picker * Match Ghostty theme picker startup * Harden cmux theme override writes * Fix DECRPM mode 2031 reporting wrong color scheme after config reload When changeConditionalState returns null (no theme-conditional config rules in the user's config), the Termio DerivedConfig inherits its conditional_state from the app-level config, which defaults to .light and is never updated. This caused colorSchemeReportLocked to always report light mode even when the surface's own color scheme was dark. Fix: after creating the Termio DerivedConfig, override its conditional_state with the surface's own config_conditional_state. This ensures the DECRPM mode 2031 response matches the actual surface color scheme. * Send initial color scheme report when mode 2031 is enabled Per the mode 2031 spec, the terminal must send an initial DSR 997 report when the mode is enabled via DECSET. Without this, clients that enable mode 2031 never receive the current color scheme. --------- Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
|
Important Review skippedToo many files! This PR contains 295 files, which is 145 over the limit of 150. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (5)
📒 Files selected for processing (295)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
4 issues found across 3000 files
Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="CONTRIBUTING.md">
<violation number="1" location="CONTRIBUTING.md:54">
P3: This link points to `.github/VOUCHED.td`, but there is no VOUCHED file in the repo, so readers will hit a broken link. Update it to an existing file or remove the link.</violation>
</file>
<file name="example/c-vt-encode-key/src/main.c">
<violation number="1" location="example/c-vt-encode-key/src/main.c:22">
P3: The example README describes encoding a Ctrl key *release* event, but the code sets the action to `GHOSTTY_KEY_ACTION_PRESS`. Update the action (or the README) so the example matches the documented behavior.</violation>
</file>
<file name="example/c-vt-render/src/main.c">
<violation number="1" location="example/c-vt-render/src/main.c:191">
P1: Ensure the grapheme buffer is at least grapheme_len elements; the fixed 16-element array can overflow when grapheme_len is larger.</violation>
</file>
<file name="example/c-vt-encode-mouse/build.zig.zon">
<violation number="1" location="example/c-vt-encode-mouse/build.zig.zon:2">
P2: Update the package name to match the example directory (and avoid duplicating the existing `c_vt` package name).</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
|
|
||
| // Read grapheme codepoints into a buffer and print them. | ||
| // The buffer must be at least grapheme_len elements. | ||
| uint32_t codepoints[16]; |
There was a problem hiding this comment.
P1: Ensure the grapheme buffer is at least grapheme_len elements; the fixed 16-element array can overflow when grapheme_len is larger.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At example/c-vt-render/src/main.c, line 191:
<comment>Ensure the grapheme buffer is at least grapheme_len elements; the fixed 16-element array can overflow when grapheme_len is larger.</comment>
<file context>
@@ -0,0 +1,234 @@
+
+ // Read grapheme codepoints into a buffer and print them.
+ // The buffer must be at least grapheme_len elements.
+ uint32_t codepoints[16];
+ uint32_t len = grapheme_len < 16 ? grapheme_len : 16;
+ ghostty_render_state_row_cells_get(
</file context>
| @@ -0,0 +1,24 @@ | |||
| .{ | |||
| .name = .c_vt, | |||
There was a problem hiding this comment.
P2: Update the package name to match the example directory (and avoid duplicating the existing c_vt package name).
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At example/c-vt-encode-mouse/build.zig.zon, line 2:
<comment>Update the package name to match the example directory (and avoid duplicating the existing `c_vt` package name).</comment>
<file context>
@@ -0,0 +1,24 @@
+.{
+ .name = .c_vt,
+ .version = "0.0.0",
+ .fingerprint = 0x413a8529a6dd3c51,
</file context>
|
|
||
| If you contributed to Ghostty prior to the introduction | ||
| of the vouch system and wish to continue contributing, you were not | ||
| automatically added to the [list of vouched users](.github/VOUCHED.td). You will need to follow the same |
There was a problem hiding this comment.
P3: This link points to .github/VOUCHED.td, but there is no VOUCHED file in the repo, so readers will hit a broken link. Update it to an existing file or remove the link.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At CONTRIBUTING.md, line 54:
<comment>This link points to `.github/VOUCHED.td`, but there is no VOUCHED file in the repo, so readers will hit a broken link. Update it to an existing file or remove the link.</comment>
<file context>
@@ -47,6 +47,13 @@ on a system of trust, and AI has unfortunately made it so we can no
+
+If you contributed to Ghostty prior to the introduction
+of the vouch system and wish to continue contributing, you were not
+automatically added to the [list of vouched users](.github/VOUCHED.td). You will need to follow the same
+process as a first-time contributor to be vouched.
+
</file context>
| automatically added to the [list of vouched users](.github/VOUCHED.td). You will need to follow the same | |
| automatically added to the list of vouched users. You will need to follow the same |
| GhosttyKeyEvent event; | ||
| result = ghostty_key_event_new(NULL, &event); | ||
| assert(result == GHOSTTY_SUCCESS); | ||
| ghostty_key_event_set_action(event, GHOSTTY_KEY_ACTION_PRESS); |
There was a problem hiding this comment.
P3: The example README describes encoding a Ctrl key release event, but the code sets the action to GHOSTTY_KEY_ACTION_PRESS. Update the action (or the README) so the example matches the documented behavior.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At example/c-vt-encode-key/src/main.c, line 22:
<comment>The example README describes encoding a Ctrl key *release* event, but the code sets the action to `GHOSTTY_KEY_ACTION_PRESS`. Update the action (or the README) so the example matches the documented behavior.</comment>
<file context>
@@ -0,0 +1,40 @@
+ GhosttyKeyEvent event;
+ result = ghostty_key_event_new(NULL, &event);
+ assert(result == GHOSTTY_SUCCESS);
+ ghostty_key_event_set_action(event, GHOSTTY_KEY_ACTION_PRESS);
+ ghostty_key_event_set_key(event, GHOSTTY_KEY_C);
+ ghostty_key_event_set_mods(event, GHOSTTY_MODS_CTRL);
</file context>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ee2595cae1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (!appendPayload(pending, payload_kind, payload_bytes)) { | ||
| parser.state = .invalid; | ||
| return null; |
There was a problem hiding this comment.
Reset pending OSC 99 state on parse failure
When appendPayload fails, the parser marks the OSC as invalid and returns without clearing parser.kitty_notification_pending. Because this pending buffer is intentionally preserved across OSC sequences, a later fragment with the same i= can be merged with stale title/body data from before the failure, producing an incorrect notification instead of dropping the partial message. Clear the pending notification state on error paths to prevent cross-sequence data contamination.
Useful? React with 👍 / 👎.
| ); | ||
| msg.write_small.len = @intCast(resp.len); | ||
| self.messageWriter(msg); | ||
| self.sendModeReport(self.terminal.modes.getReport(.{ .value = @truncate(mode_raw), .ansi = ansi })); |
There was a problem hiding this comment.
Preserve full mode number in unknown DECRPM replies
This truncates mode_raw (u16) into a 15-bit ModeTag value before encoding the response, so unknown mode queries above 32767 are echoed back as a different mode number (e.g. 40000 becomes 7232). That changes protocol-visible behavior for DECRPM unknown-mode replies and can break clients that rely on the returned mode id matching the requested one.
Useful? React with 👍 / 👎.
Upstream restructured the OSC parser, replacing the old `writer` field and `writeToFixed()` method with the new `capture`/`captureTrailing()` API. Update the kitty notification parser to use the new capture API.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f2f7b140d0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| fn requestModeUnknown(self: *Handler, mode_raw: u16, ansi: bool) void { | ||
| const report = self.terminal.modes.getReport(.{ | ||
| .value = @truncate(mode_raw), |
There was a problem hiding this comment.
Preserve full mode ID in unknown DECRPM replies
Avoid truncating unknown mode queries before encoding the response. In requestModeUnknown, @truncate(mode_raw) narrows a u16 mode number into the 15-bit ModeTag, so queries above 32767 are echoed back as a different mode id (for example, 40000 becomes 7232). That makes protocol-visible DECRPM responses incorrect for clients that correlate replies to the original requested mode.
Useful? React with 👍 / 👎.
5268b1f to
ce2181d
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ce2181d52d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (!pending.active or !std.mem.eql(u8, pending.idSlice(), value)) { | ||
| pending.reset(); | ||
| pending.active = true; | ||
| pending.id_len = @min(value.len, pending.id.len); | ||
| @memcpy(pending.id[0..pending.id_len], value[0..pending.id_len]); |
There was a problem hiding this comment.
Preserve full OSC 99 chunk IDs
The chunk-merging logic truncates i= values to 64 bytes when storing them, but subsequent chunks are compared against the full incoming ID. For any ID longer than 64 bytes, std.mem.eql at the next chunk always fails due to the length mismatch, so the pending title/body state is reset and multipart notifications with long IDs cannot be reassembled correctly. Please either reject oversized IDs up front or store/compare IDs without truncation.
Useful? React with 👍 / 👎.
Upstream removed ghostty_surface_clear_selection and never had ghostty_surface_select_cursor_cell. Both are needed by cmux for keyboard copy mode. Re-add implementations.
ce2181d to
fa0769f
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fa0769f3f5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (payload_kind == .ignore) { | ||
| return null; |
There was a problem hiding this comment.
Clear partial OSC 99 state when control packets are ignored
Returning immediately for p=close/p=alive leaves kitty_notification_pending untouched, so an in-progress multipart notification (d=0) can survive across those control packets and be incorrectly merged into a later notification that reuses the same i= value. This produces stale title/body concatenation instead of starting a fresh notification, so ignored control packets should reset (or ID-match reset) the pending buffer.
Useful? React with 👍 / 👎.
Swift/Xcode can't import the new SET_TAB_TITLE enum value, causing all subsequent values to shift by 1. This makes the app misinterpret actions (e.g. COMMAND_FINISHED matches as START_SEARCH, crashing). Move set_tab_title to the end of the C ABI Key enum so existing values keep their positions.
d2358b5 to
40c3dcd
Compare
Summary
Rebases cmux patches onto latest upstream ghostty (
upstream/main), catching up from Feb 17 to Mar 30.This brings in the fix for the click-after-tab-switch infinite scroll bug (manaflow-ai/cmux#1199) via upstream ghostty-org#11167.
Carried forward (13 cmux patches):
Dropped:
Summary by cubic
Sync cmux with upstream ghostty (through 2026‑03‑30) to fix the post‑tab‑switch infinite scroll bug and ship major
libghostty/Windows upgrades, plus a README/roadmap overhaul makinglibghosttya first‑class target. Also adds a top‑level CMake wrapper and many C/CMake examples for easier embedding.New Features
TerminalStreamwith effect callbacks and replies for DECRQM, DSR (operating status, cursor, color scheme), device attributes (DA1/DA2/DA3), kitty keyboard, XTVERSION, ENQ, window title, and size (XTWINOPS).ghostty_alloc/ghostty_free;ghostty_terminal_setoptions forwrite_pty,bell,title_changed,enquiry,xtversion,size,color_scheme, anddevice_attributes.fg_color/bg_colorinGhosttyRenderStateRowCellsData(invalid when unset so callers can fall back).zig build -Demit-lib-vt, installable shared/staticghostty-vttargets, andghostty-vt-config.cmakeforfind_package/FetchContent; Windows import‑lib placement and Ninja OUTPUT fixes.Build & CI
libghostty-vtbuilds/tests via VirtualAlloc paging, CRLF X11 color parsing, Windows path/colon config parsing,ssize_ttypedef, default MSVC ABI and C++17 flags, LLVM backend, skip/bundle fixes forcompiler_rt/ubsan_rt, linkntdll/kernel32; fixedzlib,freetype(headers/enums),glslang(C++17, nolinkLibCpp),oniguruma; helpgen/framegen stdout/scandir fixes; increased comptime quota; static lib namedghostty-vt-static.lib.test-lib-vtand a “skip” gating job; removed continue‑on‑error on Windows; action pins updated; Vouch CODEOWNERS sync workflow; SwiftLint config/checks;.gitattributesline‑ending rules; README/HACKING updates.Written for commit 40c3dcd. Summary will update on new commits.