Skip to content

jj: stale-WC tolerant list / remove / prune #20

@yukimemi

Description

@yukimemi

What

renri list, renri remove <branch>, and renri prune all surface jj's raw "stale working copy" error when the calling workspace's snapshot is behind the operation log:

Error: jj workspace list: Error: The working copy is stale (not updated since operation aa93561903e7).
Hint: Run `jj workspace update-stale` to update it.

This is a different "stale" from the one prune already handles (workspace whose root directory has been deleted). It's the op-log stale that happens when something changes git refs / jj ops out from under a workspace that already snapshotted — for example, git fetch after a remote-side merge.

Repro

From the main checkout:

  1. gh pr merge <pr> --squash --delete-branch
  2. git fetch origin main (or any flow that nudges jj's underlying git store)
  3. renri remove <branch> — fails with the stale-WC error above

renri prune and renri list hit the same error (all three call jj workspace list early).

Why it matters

  • The post-merge cleanup workflow documented in CLAUDE.md (renri remove <branch> then optionally renri prune) breaks until the user manually runs jj workspace update-stale from the main checkout.
  • The error message is clear, but renri swallows context (which command, which workspace) and the user has to translate the jj jargon. New jj users hit a wall.

Proposal

Detect the stale-WC error in the jj backend's command runner and either:

a) Emit a renri-flavored hint — wrap the jj error with something like:

the main checkout's jj working copy is behind. Run jj workspace update-stale in <root> and retry.

Safest option, no implicit mutation.

b) Auto-recover for read-only paths (list) and bail-with-hint for mutating paths (remove, prune). update-stale is itself read-only-ish (it only fast-forwards the current workspace's @ to match the latest op), but doing it implicitly when the user asked for remove could mask deeper conflicts.

(a) is the lower-risk default. (b) is nicer UX but warrants explicit opt-in.

Out of scope

  • Making renri itself robust to target workspace staleness (i.e. "remove a stale workspace") — prune already handles that case via is_stale || !path.exists().
  • Equivalent stale-WC concept for git worktrees — git's model doesn't have an op log so there's no analog.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions