Skip to content

Release v0.75.0 - #3924

Merged
max-sixty merged 7 commits into
mainfrom
codex/release-2026-08-26
Aug 27, 2026
Merged

max-sixty merged 7 commits into
mainfrom
codex/release-2026-08-26

Conversation

@max-sixty

@max-sixty max-sixty commented Aug 26, 2026 •

Copy link
Copy Markdown
Owner

Summary

Release Worktrunk 0.75.0. The user-facing release adds the unified picker diff and raises the minimum Git version to 2.43, while correcting list collection gates and conflict checks, timed child cleanup, long Windows paths, shell configuration concurrency, diagnostic profiling, and fenced HTML handling.

The release also updates agent and worktree guidance, the wt up recipe, the docs site, and library API notes. Release preparation found and fixed a concurrent rc-file overwrite in the shell installation path before tagging. The final implementation locks and rereads the open rc file, offers the addition in one write attempt, and reports a proven short write without truncating user or concurrent data.

Validation

  • cargo run -- hook pre-merge --yes — 4,707 tests passed, 1 skipped; Clippy, formatting, lockfile, docs, doctests, snapshots, and repository policy hooks passed
  • task coverage — 4,707 tests passed with shell-integration coverage enabled; every deterministic new path is covered, leaving only the OS lock-error backstop uncovered
  • Exact-cut nightly run — all 14 jobs passed at 7f5d245983317bcd5c3d798739b4d8f4f3fe7d0a
  • cargo-semver-checks 0.50.0 — confirmed breaking public library API changes, requiring the pre-1.0 minor bump
  • cargo check
  • cargo test --bin wt md_help — 27 passed after merging the latest test-only drift from the default branch

This was written by Codex on behalf of @max-sixty

@worktrunk-bot worktrunk-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the release mechanics (version bump, changelog coverage against the 47 PRs merged since v0.74.0) and the two code commits the branch carries. The changelog reads accurate — I spot-checked the Git 2.43 entry against command_requires_supported_git in src/main.rs, which does exempt exactly wt config shell. Three things below.

The one I'd want resolved before merge is the rc-file append: swapping write_atomically for write_all on the user's ~/.zshrc trades a whole-file race for a torn-line risk, and there's no rollback. write_all returns Err after having written some bytes when the underlying write short-writes and then fails — ENOSPC or a quota hit during wt config shell install leaves ~/.zshrc ending in a half-written if command -v wt >/dev/null 2>&1; then eval "$(comm, an unterminated quote that breaks every new shell. Under write_atomically the same failure left the file untouched. We hold the exclusive lock and know the pre-write length, so the truncate-back is cheap; inline suggestion on the write.

Separately, the new CLAUDE.md clause is stronger than the code. "never truncate or rebuild such a file" is contradicted by uninstall_previewed_lines in the very file this diff edits — it reads the rc file, filters lines, and hands the whole rebuilt string to write_atomically (the function whose own spec in src/utils.rs still opens "Every file that reaches this function is one a torn write breaks — rc files and shell wrappers the user's shell sources at startup"). So the two docs now disagree about whether rc files are a write_atomically client. Worth noting too that the lock closes only the install half of the read-modify-write: uninstall takes no lock, so wt config shell uninstall racing an install still drops the appended line. The changelog's "overlapping installs lock and reread rc files" is precise about this; CLAUDE.md's absolute is not.

Angles that came back clean
  • src/git/repository/diff.rs — as_chunks::<2>().0.iter() is behaviour-identical to chunks_exact(2): the remainder is discarded either way and pair[0]/pair[1] index a [String; 2] the same as a 2-element slice. MSRV is fine — lint runs pre-commit's clippy on the pinned 1.97 toolchain and passed.
  • Hard-link and inode preservation is a genuine improvement over the rename, and test_configure_shell_appends_without_replacing_existing_file pins it.
  • Symlinked rc files (chezmoi/stow) still work: append mode writes through the link, same net effect as write_atomically's canonicalize step.
  • No duplication — contains_shell_integration is an extraction from the inline loop, and acquire_config_lock in src/config/user/mutation.rs locks a sidecar .lock, so it isn't reusable for an rc file.
  • Bundling code fixes into the release commit matches the v0.72.0 and v0.74.0 release PRs, so not flagging it.

One small gap: test_configure_shell_rereads_open_file_before_appending calls append_shell_integration_if_missing directly, so nothing exercises configure_shell_file's open → lock → recheck wiring end to end. A refactor that dropped the lock_exclusive() call would keep both new tests green.

Not approving — the partial-write path is a new way for wt to leave a user's shell startup broken, which is the failure class the Data Safety section in CLAUDE.md exists for, and it's your call whether the rollback is worth the four lines.

Comment thread src/commands/configure_shell.rs Outdated
Comment thread CLAUDE.md Outdated
Comment thread CHANGELOG.md Outdated
@max-sixty

Copy link
Copy Markdown
Owner Author

pre-commit.ci run

This was posted by Codex on behalf of @max-sixty

@worktrunk-bot worktrunk-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

89d248c2e clears all three earlier threads: the append path reports a short write instead of truncating, CLAUDE.md now scopes the append rule to install and points at uninstall_previewed_lines for the rewrite direction, and the changelog entry links both PRs. Declining to retry the remainder of a short write is the right call for an O_APPEND handle — retrying would let a non-wt appender interleave between the two writes and split the line, which the exclusive lock can't prevent.

One new problem, in the added test_configure_shell_opens_rc_with_exclusive_lock: the WouldBlock assertion is Unix-only and will fail test (windows).

try_lock_exclusive here is fs2::FileExt's — std has try_lock/try_lock_shared but no try_lock_exclusive, so no inherent method shadows the trait. On Unix fs2 maps contention to EWOULDBLOCK, which decodes to ErrorKind::WouldBlock. On Windows its lock_file returns Error::last_os_error() after a failed LockFileEx(… | LOCKFILE_FAIL_IMMEDIATELY), i.e. ERROR_LOCK_VIOLATION (33), and std's Windows decode_error_kind has no arm for that value — it falls through to Uncategorized. (WSAEWOULDBLOCK is 10035, a separate arm in the second match.) fs2's own test suite compares raw_os_error() against lock_contended_error() rather than comparing kinds, for exactly this reason, and this repo already does the portable thing: fixture_lock_excludes_an_independent_handle in tests/helpers/wt-perf/src/lib.rs asserts only try_lock_exclusive().is_err(). test (macos) passing on this head is consistent with the Unix half of that.

The inline suggestion swaps the kind comparison for fs2::lock_contended_error().raw_os_error(), which keeps the assertion able to tell contention apart from an unrelated open/lock error. Bare .is_err() matching the wt-perf test is fine too.

Not approving while a test the commit adds is red on one platform.

Comment thread src/commands/configure_shell.rs Outdated
@max-sixty
max-sixty merged commit 24d09cf into main Aug 27, 2026
60 of 61 checks passed
@max-sixty
max-sixty deleted the codex/release-2026-08-26 branch August 27, 2026 03:10
social4hyq pushed a commit to social4hyq/homebrew-core that referenced this pull request Sep 20, 2026
worktrunk 0.75.0

Created-by: HarmonybrewBot
Commit-by: HarmonybrewBot
Merged-by: HarmonybrewBot
Description: Created by `brew bump`

---

Created with `brew bump-formula-pr`.<details>
  <summary>release notes</summary>
  <pre>## Release Notes

### Improved

- **The `wt switch` picker opens on one unified diff**: local rows combine committed, staged, unstaged, and untracked changes. Tab skips empty subsidiary views, while `Alt-1` through `Alt-8` retain direct access. [Docs](https://worktrunk.dev/switch/#interactive-picker) ([#3865](max-sixty/worktrunk#3865))

- **Git 2.43 is now the minimum supported version**: older Git exits with an upgrade message before Git-dependent commands run; `wt config shell` remains available so shell startup continues. (Breaking.) ([#3895](max-sixty/worktrunk#3895))

### Fixed

- **`wt list` no longer grows `.git/objects` during advisory conflict checks**: untracked content stays visible but is excluded from synthetic trees, and all probe-only objects use temporary storage. ([#3906](max-sixty/worktrunk#3906), fixes [#3883](max-sixty/worktrunk#3883), thanks @srobroek for reporting and the original fix)

- **`HEAD±` counts untracked files without inflating moves**: `wt list`, the picker, and statusline include untracked lines. Tracked deletions paired with untracked destinations count as renames, so pure moves are line-neutral and edited moves show only their edits. `HEAD±` now always detects renames, regardless of `diff.renames`. ([#3925](max-sixty/worktrunk#3925))

- **Timed child processes no longer abort `wt` in restricted sandboxes**: `wt switch --create`, picker pagers, and other bounded commands survive denied signal-handler wakes. TERM→KILL cleanup also returns promptly once the process group is gone. ([#3857](max-sixty/worktrunk#3857), [#3887](max-sixty/worktrunk#3887), fixes [#3856](max-sixty/worktrunk#3856), thanks @tomascamargo for reporting)

- **JSON list output ignores display-column gates**: `[list] columns` no longer makes `wt list --format json` contact a forge or generate summaries. CI requires `--full`; summaries also require `[list] summary = true` and a configured generator. (Breaking: schema 1 loses config-driven `ci` and `summary` fields.) ([#3812](max-sixty/worktrunk#3812), thanks @emeren for the request)

- **Long Windows paths compare consistently**: paths beyond 260 characters could retain a `\\?\` prefix and appear to be on another drive. `copy-ignored` then refused them, while switch, remove, merge, and relocate landed at the worktree root instead of the original subdirectory. ([#3899](max-sixty/worktrunk#3899), fixes [#3898](max-sixty/worktrunk#3898), thanks @Persedes for reporting and verifying the fix)

- **Shell configuration rechecks before it writes**: overlapping installs lock and reread rc files; Fish completion installs preserve files created after preview; uninstall applies only previewed rc removals and rejects changed Worktrunk-owned files. ([#3853](max-sixty/worktrunk#3853), [#3924](max-sixty/worktrunk#3924))

- **`-vv` profiles exclude their own collector commands**: command counts and cache summaries no longer include duplicate-looking work performed only to assemble the diagnostic report; raw traces still retain it. ([#3900](max-sixty/worktrunk#3900))

- **Fenced HTML comments survive picker Markdown rendering**: PR descriptions and comments now preserve fenced `<!-- … -->` lines; fenced `<!-- wt list … -->` markers also no longer affect the following block. ([#3908](max-sixty/worktrunk#3908))

### Documentation

- **Agent CLIs without a plugin can publish activity markers**: the integration guide now specifies the session-start, turn-end, and session-end calls, working-directory requirement, error guard, and cleanup contract. [Docs](https://worktrunk.dev/claude-code/#agent-clis-without-a-plugin) ([#3848](max-sixty/worktrunk#3848), thanks @AsafMah for requesting generic-agent guidance and @ortonomy for the related Pi use case)

- **Agent guidance explains worktree selection**: commands that name a branch already select its worktree; `-C` changes repository context and is needed only for commands without a worktree selector or callers outside the repository. ([#3890](max-sixty/worktrunk#3890))

- **The `wt up` recipe safely updates dirty worktrees**: it fetches all remotes, fast-forwards dirty branches without autostash, rebases clean branches, and continues past an ordinary refusal or a failed remote. [Docs](https://worktrunk.dev/extending/#recipe-rebase-every-worktree-onto-its-upstream) ([#3882](max-sixty/worktrunk#3882))

- **The docs site has a new responsive design**: rebuilt on Astro and Starlight while preserving public routes, anchors, and crawler URLs; generated reference pages remain synchronized. ([#3866](max-sixty/worktrunk#3866))

### Internal

- **Library API rework** (Breaking library API): `BranchDiffSpec` gained `working_base`, while remote-URL, shell-path, branch-push, approval, temporary-index, and repository helpers were removed. ([#3833](max-sixty/worktrunk#3833), [#3853](max-sixty/worktrunk#3853), [#3865](max-sixty/worktrunk#3865), [#3866](max-sixty/worktrunk#3866), [#3875](max-sixty/worktrunk#3875))

- **Codex loads repository maintainer skills**: `.agents/skills` now exposes the canonical `.claude/skills` tree; checkouts without symlink support keep the existing limitation. ([#3903](max-sixty/worktrunk#3903))

## Install worktrunk 0.75.0

### Install prebuilt binaries via shell script

```sh
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/max-sixty/worktrunk/releases/download/v0.75.0/worktrunk-installer.sh | sh && wt config shell install
```

### Install prebuilt binaries via powershell script

```sh
powershell -ExecutionPolicy Bypass -c "irm https://github.com/max-sixty/worktrunk/releases/download/v0.75.0/worktrunk-installer.ps1 | iex"; git-wt config shell install
```

### Install prebuilt binaries via Homebrew

```sh
brew install worktrunk && wt config shell install
```

## Download worktrunk 0.75.0

|  File  | Platform | Checksum |
|--------|----------|----------|
| [worktrunk-aarch64-apple-darwin.tar.xz](https://github.com/max-sixty/worktrunk/releases/download/v0.75.0/worktrunk-aarch64-apple-darwin.tar.xz) | Apple Silicon macOS | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.75.0/worktrunk-aarch64-apple-darwin.tar.xz.sha256) |
| [worktrunk-x86_64-apple-darwin.tar.xz](https://github.com/max-sixty/worktrunk/releases/download/v0.75.0/worktrunk-x86_64-apple-darwin.tar.xz) | Intel macOS | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.75.0/worktrunk-x86_64-apple-darwin.tar.xz.sha256) |
| [worktrunk-x86_64-pc-windows-msvc.zip](https://github.com/max-sixty/worktrunk/releases/download/v0.75.0/worktrunk-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.75.0/worktrunk-x86_64-pc-windows-msvc.zip.sha256) |
| [worktrunk-aarch64-unknown-linux-musl.tar.xz](https://github.com/max-sixty/worktrunk/releases/download/v0.75.0/worktrunk-aarch64-unknown-linux-musl.tar.xz) | ARM64 MUSL Linux | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.75.0/worktrunk-aarch64-unknown-linux-musl.tar.xz.sha256) |
| [worktrunk-x86_64-unknown-linux-musl.tar.xz](https://github.com/max-sixty/worktrunk/releases/download/v0.75.0/worktrunk-x86_64-unknown-linux-musl.tar.xz) | x64 MUSL Linux | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.75.0/worktrunk-x86_64-unknown-linux-musl.tar.xz.sha256) |



### Install via Cargo

```sh
cargo install worktrunk && wt config shell install
```

### Install via Winget (Windows)

```sh
winget install max-sixty.worktrunk && git-wt config shell install
```

### Install via AUR (Arch Linux)

```sh
paru worktrunk-bin && wt config shell install
```
</pre>
  <p>View the full release notes at <a href="https://github.com/max-sixty/worktrunk/releases/tag/v0.75.0">https://github.com/max-sixty/worktrunk/releases/tag/v0.75.0</a>.</p>
</details>
<hr>

See merge request: Harmonybrew/homebrew-core!17938
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants