Skip to content

fix(state): don't repopulate default-branch cache on state get - #3024

Merged
max-sixty merged 1 commit into
mainfrom
default-branch-state
Jun 10, 2026
Merged

max-sixty merged 1 commit into
mainfrom
default-branch-state

Conversation

@max-sixty

Copy link
Copy Markdown
Owner

wt config state get rendered its DEFAULT BRANCH section through default_branch(), the detect-and-cache resolver. On an empty cache that resolver re-detects and persists, so running wt config state get right after wt config state clear silently rewrote the worktrunk.default-branch value the clear had just removed. The cleared state was real but invisible: inspecting it re-created it. On a cold clone the same path could fire git ls-remote from a command that's meant to be pure inspection.

The aggregate dump now reads the cache read-only through a new cached_default_branch() accessor, in both the text and JSON paths. This matches how the dump's CI section already reads CachedCiStatus without fetching, so every section of state get is now a faithful, side-effect-free readout. An empty cache shows (none) (text) / null (JSON), consistent with the sibling sections.

wt config state default-branch get is unchanged: it still resolves and caches, because that command's job is to determine the default branch (e.g. git rebase $(wt config state default-branch)), not to report stored state.

The two comprehensive state get tests now seed worktrunk.default-branch so they exercise the populated path; the empty/CI/logs tests exercise the (none)/null path.

This was written by Claude Code on behalf of max

`wt config state get` rendered the DEFAULT BRANCH section via
`default_branch()`, the detect-and-cache resolver. On an empty cache that
re-detects and persists, so inspecting state silently rewrote the
`worktrunk.default-branch` value a preceding `state clear` had just removed. On
a cold clone it could even fire `git ls-remote` from an inspection command.

The dump now reads the cache read-only through a new `cached_default_branch()`
accessor (both text and JSON), matching how the CI section already reads
`CachedCiStatus` without fetching. An empty cache shows `(none)`.

`wt config state default-branch get` still resolves and caches. That command
determines the default branch rather than reporting stored state.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@max-sixty
max-sixty merged commit 12d904c into main Jun 10, 2026
36 checks passed
@max-sixty
max-sixty deleted the default-branch-state branch June 10, 2026 03:39
max-sixty added a commit that referenced this pull request Jun 10, 2026
Documentation follow-up to #3024 (which made `wt config state get` read
the default-branch cache read-only).

After that change the dump shows `DEFAULT BRANCH (none)` right after a
`clear`, while `wt config state default-branch get` still returns the
resolved branch. That contrast can read as inconsistent. Two small
additions make the model explicit:

- The `default-branch` `--help` gains one line: `default-branch get`
resolves and caches; the aggregate `wt config state get` only reports
the cache, so it can show `(none)` until something populates it.
- The `state` module spec gains a "Reading vs resolving" section
recording the invariant for future developers: the aggregate `get`
inspects read-only (`cached_default_branch()`,
`CachedCiStatus::list_all`), while a per-key `get` for a derived value
resolves it (`default_branch()`, `PrStatus::detect`).

No behavior change. The `docs/` and `skills/` mirrors and the `--help`
snapshot are regenerated from the source.

> _This was written by Claude Code on behalf of max_

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
social4hyq pushed a commit to social4hyq/homebrew-core that referenced this pull request Sep 20, 2026
worktrunk 0.58.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

- **Table-form `pre-*` hooks run concurrently**: A multi-entry table hook (`[pre-merge]` with several keys) now runs its commands concurrently, completing the cut-over announced in v0.37.0: every hook type has one execution semantic, where table form is concurrent and pipeline form (`[[pre-merge]]` blocks) is serial. Configs that need ordering should use pipeline form; affected configs have warned on every invocation since v0.37.0, with `wt config update` offering a serial-preserving migration. Two adjacent inconsistencies are also gone: `wt hook <post-type>` foreground runs of multi-entry table hooks now run concurrently like their background counterpart, and single-entry table aliases write to stdout like the other alias spellings, so `wt <alias> | …` works for that spelling too. (Breaking: multi-entry table-form `pre-*` hooks no longer run serially) ([#3052](max-sixty/worktrunk#3052))

- **CI column shows the PR/MR number and review state**: The CI column in `wt list --full` and the statusline shows the branch's open PR/MR reference (`#3041` on GitHub/Gitea/Azure DevOps, `!3041` on GitLab) instead of a plain dot: colored by CI status, hyperlinked to the PR, dimmed when stale or draft. Review state folds into the color, with magenta for changes requested and cyan for awaiting review. `wt list --format=json` gains `ci.number` and `ci.review_state`. ([#3041](max-sixty/worktrunk#3041), [#3044](max-sixty/worktrunk#3044))

- **Hook and alias templates render when each step runs**: Templates are syntax-checked before the first step runs and rendered as each step executes, so `{{ vars.* }}` always reads fresh values and hooks and aliases share one expansion model. Two consequences: a pipeline step with an undefined variable fails when that step is reached (earlier steps run first), and a template error in a background hook surfaces in the hook log rather than failing the foreground command. The background runner also labels template errors the way the foreground does. ([#3042](max-sixty/worktrunk#3042), [#3047](max-sixty/worktrunk#3047))

- **`wt config state cache`**: The regenerable caches (CI status, branch summaries, git-command caches, hints, the `wt switch -` target) are consolidated under `wt config state cache`; `cache clear` drops them all without prompting, since everything regenerates. `wt config state clear`, which also wipes hand-authored markers and vars, now asks for confirmation; `--yes` skips, and non-interactive runs without `--yes` cancel. The `ci-status`, `hints`, and `previous-branch` subcommands are deprecated but still work. ([#3027](max-sixty/worktrunk#3027))

- **Statusline rate-limit segment**: Above 90% of the binding window the segment shows the used percentage (`95%(8:30am–1:30pm)`) instead of the pace ratio; near the cap, what's left matters more than the rate. The pace form drops the word "pace" (`2.9×(Tue–Tue 5pm)`), and `-vv` logs each window's inputs and selection to `.git/wt/logs/trace.log` so the binding-window choice can be reconstructed. ([#3057](max-sixty/worktrunk#3057), [#3053](max-sixty/worktrunk#3053), [#3029](max-sixty/worktrunk#3029))

- **`/wt-switch-create` branch name is optional**: The Claude Code plugin command picks a branch name from the task when none is given, and the skill's workflow is one route (create, then enter) with an error-driven fallback instead of three guarded paths. Worktrees created mid-session persist after the session ends. ([#3058](max-sixty/worktrunk#3058))

### Fixed

- **Plugin worktree hooks fail before side effects**: The Claude Code plugin's `WorktreeCreate`/`WorktreeRemove` hooks validate the payload before running `wt`; a malformed payload previously created a branch named `null` or could remove the wrong worktree. `wt remove`'s help now documents that the positional argument accepts a worktree path as well as a branch name. ([#3058](max-sixty/worktrunk#3058), [#3060](max-sixty/worktrunk#3060))

- **Waiting-for-input marker covers questions, permission prompts, and turn end**: The Claude Code plugin sets the 💬 marker on `AskUserQuestion`, permission requests, and turn end. Previously only the `Notification` event set it, which never fires for the built-in question picker (and on some platforms not for permission prompts), so the marker stayed 🤖 while Claude waited. Part of [#2916](max-sixty/worktrunk#2916). ([#3023](max-sixty/worktrunk#3023), thanks @Ismael for reporting)

- **`wt list --help` no longer panics when piped**: With no detectable terminal width (output piped, `COLUMNS` unset), `wt list --help` panicked with a capacity overflow, and the post-commit diffstat truncated filenames to ~10 characters. Both now handle unknown width. ([#3040](max-sixty/worktrunk#3040))

- **Deprecation warnings match `wt config update`**: A config deprecation warning now fires exactly when `wt config update` would change the file. The old detection and migration logic had drifted in several places: `ff` and `no-ff` together silently dropped `no-ff`, a scalar `forge` key was overwritten by the `[ci]` migration, an empty `[ci] platform` migrated without warning, and an empty `approved-commands = []` could be removed by an unrelated update. ([#3055](max-sixty/worktrunk#3055))

- **Migrated `[forge]` keeps `[ci]`'s spot**: The `[ci]` → `[forge]` migration rendered the new section at the end of the file and could drop comments above `[ci]`; it now takes over `[ci]`'s position, comments included, so `wt config show` and `wt config update` diffs stay minimal. ([#3051](max-sixty/worktrunk#3051))

- **`wt config state get` is read-only**: The aggregate dump resolved (and re-cached) the default branch, so running it right after `clear` silently repopulated the cache, and on a cold clone it could hit the network. It now reports the cached value or `(none)`. `wt config state default-branch get` still resolves and caches. ([#3024](max-sixty/worktrunk#3024))

### Documentation

- **Reading vs resolving cached state**: `wt config state default-branch get` resolves and caches; the aggregate `wt config state get` only reports the cache. The help text and module docs now state the split. ([#3028](max-sixty/worktrunk#3028))

### Internal

- `wt switch`/`wt remove` orchestration moved from `main.rs` to their command modules, and the hook execution call chain lost two delegation layers. ([#3049](max-sixty/worktrunk#3049), [#3036](max-sixty/worktrunk#3036))

- Config deprecations are driven by a single rule table; each rule is one function that migrates and reports what it changed. ([#3045](max-sixty/worktrunk#3045), [#3055](max-sixty/worktrunk#3055))

- `terminal_width()` returns `Option<usize>` instead of a `usize::MAX` sentinel, making the no-width case a compile-time concern. ([#3043](max-sixty/worktrunk#3043))

- Snapshot tests regenerate identically across machines: host-specific paths are guarded, host-dependent env-block markers are normalized, and help snapshots share one settings builder. ([#3009](max-sixty/worktrunk#3009), [#3026](max-sixty/worktrunk#3026), [#3037](max-sixty/worktrunk#3037), [#3061](max-sixty/worktrunk#3061))

- Nightly CI runs lib tests across the full feature powerset. ([#3059](max-sixty/worktrunk#3059))

- MSRV bumped from 1.94 to 1.95. ([#2948](max-sixty/worktrunk#2948))

## Install worktrunk 0.58.0

### Install prebuilt binaries via shell script

```sh
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/max-sixty/worktrunk/releases/download/v0.58.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.58.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.58.0

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

See merge request: Harmonybrew/homebrew-core!11501
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